\section{Nombre}

\texttt{Bench::Test::Base}

Lectura de archivos \texttt{.base} creados con el modulo \texttt{Bench::Test}

\section{Sinopsis}

\begin{verbatim}
   my $local = Bench::Test::Base->new(
      WORKDIR   => '.',
   );
\end{verbatim}
\begin{verbatim}
   my $output = $base->get_result($testname);
\end{verbatim}

\section{Descripción}

El objeto \texttt{Bench::Test::Base} permite acceder al contenido
de un fichero de texto cuyo contenido es el resultado de las ejecuciones creadas
con los métodos \texttt{save\_result} de las clases \texttt{Bench::Test::Local} y
\texttt{Bench::Test::Remote}.

\subsection{Un ejemplo}

Supongamos un fichero \texttt{.base} cuyo contenido sea el siguiente:

\begin{verbatim}
   ~/projects/Bench-Test/examples/mm$ cat dat/mm_200.base
   Filas primera matriz: 200
   Filas segunda matriz: 200
   Columnas segunda matriz: 200
   Time of product: 0.210942
   Result: 4102
\end{verbatim}

Creamos un objeto \texttt{Bench::Test::Local} de la siguiente forma:

\begin{verbatim}
   $base = Bench::Test::Base->new
      WORKDIR   => 'dat',
   );
\end{verbatim}

Con una llamada a \texttt{get\_result} como la que sigue:

\begin{verbatim}
   my $output = $base->get_result('mm_200');
\end{verbatim}

Obtendríamos en la variable \texttt{\$output} el contenido del fichero \texttt{mm\_200.base}.

\section{Métodos}

\subsection{El constructor \texttt{new}}

Véase una llamada típica:

\begin{verbatim}
   $base = Bench::Test::Base->new
      WORKDIR   => 'dat',
   );
\end{verbatim}

El constructor acepta los siguientes parámetros:

\begin{description}

\item[{\texttt{WORKDIR:}}] \mbox{}

Directorio de trabajo donde se encuentran los
archivos \texttt{.base} de donde se leerán las salidas
de las ejecuciones anteriormente almacenadas.

\end{description}

\subsection{El método \texttt{get\_result}}

El método \texttt{get\_result} recibe una cadena con el
nombre del test y devuelve el contenido del fichero
de texto asociado a dicho test. Por ejemplo, si el
atributo \texttt{WORKDIR} es \texttt{/dat} y el nombre del 
test es \texttt{mm\_100}, el método \texttt{get\_result} devuelve
el contenido del archivo \texttt{/dat/mm\_100.base}

\section{Véase también}

Para una mejor comprensión del módulo \texttt{Bench::Test::Base}, véase también la
documentación de los siguientes módulos:

\begin{itemize}
\item \texttt{Bench::Test}
\item \texttt{Bench::Test::Local}
\item \texttt{Bench::Test::Remote}
\end{itemize}
\section{El script}

Como ayuda al usuario se proporciona junto con la
distribución de \texttt{Bench::Test} el script
\texttt{configcreate} que facilita al usuario la
escritura de los ficheros de con\-fi\-gu\-ra\-ción.

Se trata de un script sencillo en modo texto
que va solicitando al usuario, paso a paso,
todos los parámetros de configuración.

Véase un ejemplo de uso para el ejemplo
del cálculo del número $\pi$:

\begin{verbatim}
   $ ./pi 10000
   
   Time: 0.000468
   Number of intervals: 10000
   Calculated Pi: 3.141593
   
   $ configcreate
   
     PARAMETRO @TABLE:
   =======================================================
     Nombre del campo:  N
     Expresión regular: Number of intervals: (.*)\n
     Nombre del campo:  PI
     Expresión regular: Calculated Pi: (.*)\n
     Nombre del campo:  TIME
     Expresión regular: Time: (.*)\n
     Nombre del campo:  
   
     PARAMETRO @TESTS:
   =======================================================
     Nombre del test:  test01
     Parámetros:       100000
     Nombre del test:  test02
     Parámetros:       200000
     Nombre del test:  test03
     Parámetros:       500000
     Nombre del test:  test04
     Parámetros:       1000000
     Nombre del test:  
   
     PARAMETRO %EXPERIMENTS:
   =======================================================
     Nombre del experimento:  LOCAL   
     Base (1), Local (2), o Remote (3):  2
   
       OBJETO Bench::Test::Local
             WORKDIR: .
          EXECUTABLE: pi
             BASEDIR: JUL_08
          OUTPUTFILE: 
            PREAMBLE: 
           POSTAMBLE: 
   
     Nombre del experimento:  
   
     PARAMETRO @VISUAL:
   =======================================================
     Incluir el campo 'TEST' ? [S/n]: s 
     Incluir el campo 'NAME' ? [S/n]: s 
     Incluir el campo 'N' ? [S/n]: s
     Incluir el campo 'PI' ? [S/n]: s
     Incluir el campo 'TIME' ? [S/n]: s
   
     PARAMETRO @UNIQUE:
   =======================================================
     Incluir el campo 'N' ? [S/n]: s     
     Incluir el campo 'PI' ? [S/n]: s
     Incluir el campo 'TIME' ? [S/n]: n 
   
     PARAMETRO @SELECTED:
   =======================================================
     Incluir el experimento 'LOCAL' ? [S/n]: s
   
     PARAMETRO @OUTPUTFORMAT:
   =======================================================
     Formato XML? [S/n]:   s
     Formato HTML? [S/n]:  s
     Formato LaTeX? [S/n]: s
     Formato Text? [S/n]:  s

     SALIDA:
   =======================================================
     Nombre del fichero [maketest.conf]: mt.conf
\end{verbatim}

\section{Resultado}

El fichero generado tendría un aspecto como el siguiente:

\begin{verbatim}
   # ==========================================
   # Configuration file for Bench::Test
   # generated by 'configcreate'
   # ==========================================
   
   @TABLE = (
      'N' => 'Number of intervals: (.*)\n',
      'PI' => 'Calculated Pi: (.*)\n',
      'TIME' => 'Time: (.*)\n',
   );
   
   @TESTS = (
      'test01' => '100000',
      'test02' => '200000',
      'test03' => '500000',
      'test04' => '1000000',
   );
   
   %EXPERIMENTS = (
      'LOCAL'
         => Bench::Test::Local->new(
                  WORKDIR => '.',
               EXECUTABLE => 'pi',
                  BASEDIR => 'JUL_08',
               OUTPUTFILE => '',
            ),
   );
   
   @VISUAL = qw(TEST NAME N PI TIME);
   
   @UNIQUE = qw(N PI TIME);
   
   @SELECTED = qw(LOCAL);
   
   @OUTPUTFORMAT = (
      'xml' => 'output.xml',
      'html' => 'output.html',
      'latex' => 'output.tex',
      'text' => 'output.txt',
   );
   
   sub Bench::Test::Entry::is_OK {
      return 1;
   }   
\end{verbatim}

\section{Aclaraciones}

Cuando el script pregunta por arrays formados por pares
clave-valor (\texttt{@TABLE}, \texttt{@TESTS} y \texttt{\%EXPERIMENTS}),
entra en un bucle del que se puede salir dejando el valor
de la clave vacío.

Los objetos de las clases \texttt{Bench::Test::Local} y
\texttt{Bench::Test::Remote} pueden definir sus parámetros
\texttt{PREAMBLE} y \texttt{POSTAMBLE}. El script
pregunta al usuario por el nombre de la rutina asociada
y no por el contenido de ésta. Una vez generado el
fichero de configuración, estas rutinas deberán
ser escritas por el usuario, al igual que la rutina
de comprobación de validez \texttt{Bench::Test::Entry::is\_OK}.
\section{Un poco de historia}

El 26 de octubre de 1995, se creó el
\textit{Comprehensive Perl Archive Network (CPAN)} \cite{CPAN}. CPAN es un enorme
archivo de software escrito en Perl, así como de documentación sobre el mismo.
Tiene presencia en la Web a través de su sitio \url{www.cpan.org} y sus más de
200 \textit{mirrors} distribuidos por todo el mundo.

Actualmente hay más de 53.000 módulos empaquetados en más de 14.000 paquetes,
aportados por más de 6.400 autores.

Se dispone de módulos para una amplia variedad de tareas, incluyendo matemáticas
avanzadas, conectividad de bases de datos y conexión de redes. Esencialmente,
todo lo que hay en CPAN está disponible de forma libre. La mayor parte del
software está licenciado bajo la Licencia Artística, la GPL o ambas.
Cualquiera puede subir software a CPAN vía \textit{PAUSE}, el
\textit{Perl Authors Upload Server} (servidor de subidas de autores Perl).

Los módulos en CPAN pueden ser descargados e instalados a mano. Sin embargo,
es muy común que los módulos dependan de otros módulos y seguir las dependencias
a mano puede ser tedioso. Tanto el módulo \texttt{CPAN.pm} (incluido en la
distribución Perl) como el módulo mejorado \texttt{CPANPLUS} ofrecen instaladores
en línea de comandos que entienden las dependencias; pueden configurarse para
descargar automáticamente e instalar un módulo y, recursivamente, todos los
módulos de los que dependa.

\section{Instalación de un módulo}

La instalación de un módulo es una tarea bastante sencilla y se puede
llevar a cabo de dos formas distintas:

\begin{itemize}
\item
Descargando el paquete e instalándolo manualmente
\item
Haciendo uso del módulo \texttt{CPAN} y el comando \texttt{cpan}
\end{itemize}

\subsection{Instalación manual}

Una vez descargado el archivo \texttt{.tar.gz} que contiene la
distribución que queremos instalar, se deben realizar los siguientes
pasos:

\begin{verbatim}
   $ perl ./Makefile.PL
   $ make
   $ make test
   $ make install
\end{verbatim}

Es recomendable antes de llevar a cabo estos pasos leer el fichero
\texttt{README} que contiene toda distribución. Es posible que
por las peculiaridades del módulo que se esté instalando haya
que realizar algún paso previo.

\subsection{Instalación con \texttt{CPAN.pm}}

Es posible instalar un módulo, supongamos \texttt{Games::Nintendo::Mario},
con el script \texttt{cpan}. Se trata de un script que hace uso
del módulo \texttt{CPAN.pm} y facilita al usuario el proceso
de instalación.

\begin{verbatim}
   $ cpan Games::Nintendo::Mario
\end{verbatim}

Este proceso de instalación es más sencillo. Como se comentó antes,
en muchas ocasiones el módulo que se desea instalar depende de
la instalación de otros módulos. La orden \texttt{cpan} permite
abstraer al usuario de dichas dependencias y llevar a cabo
el proceso de instalación correctamente.
\section{El script}

Como ayuda al usuario se proporciona junto con la
distribución de \texttt{Bench::Test} el script
\texttt{createtests} que facilita al usuario la
utilización del módulo. Se trata de un script
sencillo cuya tarea es crear un objeto de la
clase \texttt{Bench::Test} e invocar al método
\texttt{create\_tests}. El constructor
toma los parámetros
desde un fichero de configuración que, por 
defecto, se llama \texttt{maketest.conf}.

La forma de uso es la siguiente:

\begin{verbatim}
   $ createtests [-f configfile]
\end{verbatim}

\section{Código}

A continuación se muestra el contenido íntegro
del script \texttt{createtests}:

\begin{verbatim}
   #!/usr/bin/perl -w

   use strict;
   use Pod::Usage;
   use Getopt::Long;
   use Bench::Test;
   use Carp;

   sub version {
     print "Version $Bench::Test::VERSION\n";
     exit;
   }

   sub usage {
     print "Usage:\n  $0 [-f configfile]\n";
     exit;
   }
   sub man {
     pod2usage(
       -exitval => 1,
       -verbose => 2
     );
   }

   # MAIN ==========================

   my $config_file = './maketest.conf';  #maketest.conf by default

   GetOptions(
     'version' => \&version,
     'usage'   => \&usage,
     'help'    => \&man,
     'file=s'  => \$config_file
   ) or croak usage();

   my $bench = new Bench::Test(
                      config_file => $config_file,
                   );

   $bench->create_tests;
\end{verbatim}
\section{Descripción del problema}

El \textbf{2DCSP} (\textit{Constrained Two-Dimensional Cutting Stock Problem} o
problema de Corte Bidimensional) se enuncia de la siguiente forma:

Se dispone de una superficie rectangular $S$ de dimensiones $L \times W$ que ha
de ser cortada en un conjunto de piezas más pequeñas utilizando cortes
ortogonales de guillotina: cualquier corte debe ir de lado a lado del
rectángulo y ser paralelo a una de las otras dos aristas.

Los rectángulos
obtenidos deben pertenecer a un conjunto dado de rectángulos o patrones
$D = \{ T_1 \dots T_n \}$ donde el $i$-ésimo patrón $T_i$ tiene dimensiones
$l_i \times w_i$ (véase la figura \ref{fig:surface-patterns}).

Cada patrón $T_i$ tiene asociado un beneficio $p_i$ y 
un límite de unidades $b_i$. El objetivo es encontrar un posible patrón
de corte con $x_i$ piezas de tipo $T_i$ que maximice el beneficio total.

\begin{displaymath}
\sum_{i=1}^{n} p_i x_i \mbox{  sujeto a  } x_i \le b_i
\end{displaymath}

\begin{figure}
  \centering
    \includegraphics[width=200pt]{images/surface-patterns.png}
  \caption{Representación de la superficie $S$ y los patrones $T_i$}
  \label{fig:surface-patterns}
\end{figure}

El problema del corte bidimensional tiene multitud de aplicaciones dentro de
distintas industrias. El material de la superficie sobre la que se
distribuirán las plantillas puede ser de diversos tipos: vidrio, metal,
tela o madera.

Se trata de un problema ampliamente estudiado, con una gran cantidad
de variantes, y que sigue teniendo a muchos investigadores trabajando
en él. Cabe destacar los trabajos de
\textit{Gilmore} y \textit{Gomory} \cite{Gil:Gom:66},
\textit{Viswanathan} y \textit{Bagchi} \cite{Bag:Vis:91}, y
\textit{Sweeney} y \textit{Paternoster} \cite{Pat:Swe}.

\newpage

\section{Resolución}

Existen numerosas formas de abordar el problema:

\begin{itemize}
\item Algoritmos de programación dinámica y variantes.
\item Métodos de programación entera. En este caso, uno de los algoritmos
más empleados es la ramificación y poda (\textit{Branch-and-Bound}).
\item Búsquedas heurísticas.
\item Aproximaciones mediante redes neuronales.
\item Aproximaciones mediante uso de sistemas expertos o sistemas basados
en el conocimiento.
\item Métodos que emplean paralelismo.
\end{itemize}

Gracias al trabajo de la compañera \textbf{Gara Miranda Valladares} he
podido disponer de una implementación brillante para la resolución de este
problema \cite{LeonMRS07}. Se trata de un algoritmo secuencial que
utiliza la técnica de \textit{Ramificación y Poda} apoyándose en una
heurística basada en \textit{Programación Dinámica} para obtener una
cota inferior que permita guiar la poda del árbol de posibles
subsoluciones.

Gracias a lo complejo del algoritmo, la cantidad de datos de interés para
el programador y la posibilidad de medir tiempos para dos soluciones
distintas (heurística y óptima), se podrá exprimir al máximo el módulo
\texttt{Bench::Test} y utilizar casi el 100\% de su funcionalidad.

\section{Instrumentación del programa}

Para que el módulo \texttt{Bench::Test} pueda realizar su labor
correctamente el programa del usuario debe estar instrumentado
de forma que todos los parámetros que le interesen sean
devueltos por el programa, ya sea volcando 
la salida en un fichero o mostrándola por pantalla
(\textit{Standard Output}). La instrumentación puede también 
automatizarse usando una herramienta adecuada \cite{call}.

El objeto \texttt{Bench::Test} lanza las ejecuciones y
obtiene la salida o la lee desde un fichero para
a continuación aplicar expresiones regulares que permitan
filtrar la información deseada. Por ello, a la hora
de instrumentar el programa se debe mostrar los
datos de forma que puedan ser fácilmente reconocidos
mediante una expresión regular.

En este problema, los valores que pueden ser interesantes
para el usuario de cara a programar posibles mejoras o analizar el
rendimiento de su implementación son los siguientes:

\begin{itemize}
\item Beneficio obtenido con la heurística
\item Tiempo que emplea la heurística
\item Nombre del problema
\item Valor de la cota superior
\item Número de nodos generados
\item Número de nodos computados
\item Beneficio de la solución óptima
\item Tiempo que emplea el algoritmo óptimo
\end{itemize}

No fue necesario realizar este paso
puesto que el programa ya estaba perfectamente instrumentado.
Véase una ejecución:

\begin{verbatim}
   $ ./cutting tests/cut2D.3.dat 
   Heuristic = 1840
   Heuristic Time: 0.040302
   
   Problem Name: tests/cut2D.3.dat
   Global Upper Bound: 2240
   Computed nodes : 1173
   Generated nodes: 1442
   Time: 0.375356
   Sequential Solution Value = 1860
\end{verbatim}

\section{Parámetros de configuración}

Una vez instrumentado el programa cliente se han de
definir los parámetros que guíen las ejecuciones. Como ya
se ha explicado anteriormente en esta memoria,
para ello existen dos posibilidades:

\begin{itemize}
\item 
Escribir un script Perl que cree un objeto de la clase
Bench::Test con los parámetros adecuados (Ver documentación
de la clase \texttt{Bench::Test} en el capítulo~\ref{chapter:Bench-Test})

\item 
Utilizar el script \texttt{maketest} proporcionado junto
con el modulo \texttt{Bench::Test} y definir los parámetros
mediante un fichero de configuración cuyo nombre, por defecto,
es \texttt{maketest.conf} (véase la documentación del script
\texttt{maketest} en el capítulo \ref{chapter:maketest})
\end{itemize}

La forma más sencilla para un usuario sin conocimientos
de Perl es escribir el fichero de configuración y hacer
uso del script proporcionado.

A continuación empezamos a escribir, paso a paso, el
fichero de configuración.

\section{Expresiones regulares}

La primera acción que realiza el objeto \texttt{Bench::Test}
después de cada ejecución es aplicar las expresiones
regulares sobre la salida generada por el programa
del usuario. Estas expresiones permiten filtrar valores de
salida en los que el usuario está interesado.

Para definirlas, se utiliza el array \texttt{@TABLE} y se
debe tener en cuenta el formato de salida del programa.

Como se vió antes, el resultado de una ejecución del
programa tiene un aspecto similar a éste:

\begin{verbatim}
   $ ./cutting tests/cut2D.3.dat 
   Heuristic = 1840
   Heuristic Time: 0.040302
   
   Problem Name: tests/cut2D.3.dat
   Global Upper Bound: 2240
   Computed nodes : 1173
   Generated nodes: 1442
   Time: 0.375356
   Sequential Solution Value = 1860
\end{verbatim}

Para filtrar dicha salida el array \texttt{@TABLE}
debería tener la siguiente forma:

\begin{verbatim}
   @TABLE = (
     OPT    => 'Sequential\s+Solution\s+Value\s*=\s*(\d+)', 
     HEUR   => 'Heuristic = (\d+)', 
     UPPER  => 'Global Upper Bound: (\d+)',
     GEN    => 'Generated\s+nodes\s*:\s*(\d+)',
     COMP   => 'Computed\s+nodes\s*:\s*(\d+)',
     INS    => 'Inserted\s+nodes\s*:\s*(\d+)',
     HTIME  => 'Heuristic\s+Time:\s*(.*)\n',
     TIME   => '\nTime:\s*(.*)\n',
     RATE  => sub {
                 my $output = shift;
                 $output =~ /Heuristic = (.*)\n(.|\n)*Value = (.*)\n/;
                 my $rate = 100 * $1 / $3;
                 return "$rate\%";
              }
   );
\end{verbatim}

Obsérvese que el array \texttt{@TABLE} está formado por
pares clave-valor cuya clave indica el nombre que el
usuario desea dar al campo objeto de estudio (no deben 
usarse los nombres \texttt{TEST} y \texttt{NAME} porque están
reservados) y cuyo valor puede ser de dos tipos:

\begin{description}

\item[{\textbf{Cadena de caracteres:}}] \mbox{}

Contiene la expresión regular que permite filtrar la salida.
Debe contar con una y sólo una parentización en el lugar donde
se encuentre el campo que queremos filtrar.

\item[{\textbf{Referencia a rutina:}}] \mbox{}

En lugar de aplicar una expresión regular sobre la salida
se deja al usuario la responsabilidad del filtrado. La rutina
recibe como parámetro la salida intacta del programa.
Esta opción es muy útil a la hora de combinar varios resultados
y devolver un solo campo.
\end{description}

En el ejemplo se utiliza una referencia a rutina para el campo
\texttt{RATE}. En dicha rutina se recoge el parámetro \texttt{\$output}
que contiene la salida de la ejecución, se le aplica una expresión
regular para filtrar los valores de beneficio de la heurística, y de
la solución óptima, y por último se devuelve el valor en porcentaje
de la \textit{tasa de acierto} o \textit{grado de acercamiento}
de la heurística con respecto a la solución óptima.

\section{Parámetros de ejecución}

Una vez definidas las expresiones regulares que filtrarán
la salida del programa, es hora de indicar los parámetros
de ejecución. El programa de este ejemplo recibe como único
parámetro el nombre de un fichero de texto que contiene la
descripción del problema. 

Suponiendo que los ficheros de datos con los problemas a resolver
se encuentran en un directorio aparte llamado \texttt{tests}, se define
el array \texttt{@TESTS} de la siguiente forma:

\begin{verbatim}
   @TESTS = (
     cut01 => 'tests/cut2D.1_.dat',
     cut02 => 'tests/cut2D.1.dat',
     cut03 => 'tests/cut2D.2_.dat',
     cut04 => 'tests/cut2D.2.dat',
     cut05 => 'tests/cut2D.3_.dat',
     cut06 => 'tests/cut2D.3.dat',
     cut07 => 'tests/cut2D.A1.dat',
     cut08 => 'tests/cut2D.A2.dat',
     cut09 => 'tests/cut2D.A3.dat',
     cut10 => 'tests/cut2D.A4.dat',
   );
\end{verbatim}

Esta definición generaría diez ejecuciones de la forma:

\begin{verbatim}
   $ <ejecutable>  tests/cut2D.1_.dat
   $ <ejecutable>  tests/cut2D.1.dat
   $ <ejecutable>  tests/cut2D.2_.dat
   $ <ejecutable>  tests/cut2D.2.dat
   $ <ejecutable>  tests/cut2D.3_.dat
   $ <ejecutable>  tests/cut2D.3.dat
   $ <ejecutable>  tests/cut2D.A1.dat
   $ <ejecutable>  tests/cut2D.A2_.dat
   $ <ejecutable>  tests/cut2D.A3.dat
   $ <ejecutable>  tests/cut2D.A4.dat
\end{verbatim}

Nótese que el array \texttt{@TESTS} está formado
por pares clave-valor. La clave indica el nombre
del test correspondiente. El nombre de este test estará
disponible al usuario como un campo llamado \texttt{NAME}
en la tabla final, como si hubiera sido definido en el
array \texttt{@TABLE}.

Si el programa de usuario sólo recibe un parámetro y ese parámetro
es un fichero (como en este caso), el módulo \texttt{Bench::Test}
dispone de una función (\texttt{get\_tests\_from\_glob}) que permite obtener
el array \texttt{@TESTS} mediante un \textit{glob} que represente a 
todos los ficheros de datos. En este caso:

\begin{verbatim}
   @TESTS = get_tests_from_glob('tests/*.dat');
\end{verbatim}


\section{Entornos de ejecución}

Todavía no se han definido en el fichero de configuración
los parámetros relacionados con el ejecutable y los entornos
de ejecución (máquinas remotas, conexiones). Para ello se utiliza
hash \texttt{\%EXPERIMENTS}.

El hash \texttt{\%EXPERIMENTS} está formado por pares clave-valor
cuyas claves son el nombre que el usuario quiere dar a
sus entornos de ejecución (por ejemplo el nombre de la máquina),
y cuyo valor es una referencia a un objeto de la clase
\texttt{Bench::Test::Base}, \texttt{Bench::Test::Local}
o \texttt{Bench::Test::Remote} (véase la documentación de
dichos módulos en los capítulos
\ref{chapter:Bench-Test-Base}, \ref{chapter:Bench-Test-Local} y 
\ref{chapter:Bench-Test-Remote}).

Para este ejemplo podríamos definir el hash \texttt{\%EXPERIMENTS} de
la siguiente forma:

\newpage

\begin{verbatim}
   %EXPERIMENTS = (
     'FEB_07' => Bench::Test::Base->new (
                    WORKDIR => 'FEB_07'
                 ),

     'LOCAL'  => Bench::Test::Local->new  (
                    WORKDIR   => '.',
                    EXECUTABLE => './cutting',
                 ),

     'ORION'  => Bench::Test::Remote->new (
                    HOST       => 'user@host',
                    WORKDIR    => '/home/user/cutting',
                    EXECUTABLE => 'cutting',
                    PREAMBLE   => \&my_preamble,
                    POSTAMBLE  => \&my_postamble,
                 ),
   );
\end{verbatim}

Esta definición contiene los tres posibles objetos: \texttt{Bench::Test::Base},
\texttt{Bench::Test::Local} y \texttt{Bench::Test::Remote}. La función de estos objetos
es definir los parámetros de ejecución en máquina local, remota o acceder
a resultados de ejecuciones anteriores previamente almacenadas.

\subsection{Objeto \texttt{Bench::Test::Base}}

El constructor de \texttt{Bench::Test::Base} recibe como único parámetro
el nombre del directorio en donde se encuentran
los ficheros con las salidas de las ejecuciones
(que fueron ejecutadas en el pasado) con las
que queremos comparar (\texttt{WORKDIR}).

El nombre del archivo a leer consiste en nombre del \texttt{test} definido
anteriormente en el array \texttt{@TESTS} seguido de la extensión
\texttt{.base} al final.

\subsection{Objeto \texttt{Bench::Test::Local}}

El objeto \texttt{Bench::Test::Local} se encarga de las ejecuciones en la 
máquina local. Su constructor recibe como parámetros la ruta al directorio
de trabajo donde se encuentra el fichero ejecutable (\texttt{WORKDIR})
y el nombre de dicho fichero (\texttt{EXECUTABLE}).

\subsection{Objeto \texttt{Bench::Test::Remote}}

El objeto \texttt{Bench::Test::Remote} permite las ejecuciones en máquinas
remotas. Su constructor recibe como parámetros el nombre del host
(y usuario, si hiciera falta) donde se van a lanzar las ejecuciones.
También recibe la ruta al directorio de trabajo y el nombre del
fichero ejecutable en la máquina remota.

Si el directorio de trabajo no existe o el ejecutable no se encuentra en
la máquina remota, pueden definirse dos parámetros (\texttt{PREAMBLE} y
\texttt{POSTAMBLE}) que permiten al usuario subir archivos y ejecutar
comandos en dicha máquina. Se trata de dos referencias a rutina
que reciben como parámetro una referencia al objeto
\texttt{GRID::Machine} con el que se ha establecido la conexión con
la máquina remota.

El módulo \texttt{GRID::Machine} \cite{CasianoGridMachineDoc}
permite subir archivos y ejecutar comandos
en la máquina remota con la que ha establecido conexión a traves
de SSH. Véase el apéndice ``\textit{El módulo} \texttt{GRID::Machine}''
en el capítulo \ref{chapter:GRID-Machine}.

En el ejemplo los valores de \texttt{PREAMBLE} y \texttt{POSTAMBLE} apuntan
respectivamente a las rutinas \texttt{my\_preamble} y \texttt{my\_postamble} que 
el usuario debe definir en el fichero de configuración. A continuación una
posible definición de estas dos rutinas:

\begin{verbatim}
   sub my_preamble {
      my $machine = shift;
      $machine->put(['cutting.tar.gz']);
      $machine->tar('cutting.tar.gz', '-xz')->ok
         or die 'Error trying to extract cutting.tar.gz';
      $machine->chdir('cutting');
      $machine->system('make');
   };

   sub my_postamble {
      my $machine = shift;
      $machine->chdir('..');
      $machine->system('rm -rf cutting');
      $machine->system('rm cutting.tar.gz');
   }
\end{verbatim}

En la rutina \texttt{my\_preamble} se toma el objeto \texttt{\$machine} de la
clase \texttt{GRID::Machine} y se utilizan los siguientes métodos:

\begin{itemize}
\item \texttt{put}: para enviar el archivo comprimido 
\texttt{cutting.tar.gz} que contiene el código fuente del programa.
\item \texttt{tar}: para descomprimir el archivo.
\item \texttt{chdir}: para cambiar al directorio de trabajo
\item \texttt{system}: para ejecutar la orden \texttt{make} y compilar el programa.
\end{itemize}

Con estos cuatro pasos, se puede automatizar la preparación del entorno de ejecución
en cada máquina remota que se defina.

En la rutina \texttt{my\_postamble} se vuelven a utilizar los métodos \texttt{chdir} para
cambiar de directorio y \texttt{system} para ejecutar comandos shell y poder borrar
los archivos subidos con la orden \texttt{rm}.

\subsection{Otros parámetros en los constructores}

A parte de los parámetros descritos en el apartado anterior, se pueden
definir dos parámetros más para los objetos de las clases \texttt{Bench::Test::Local}
y \texttt{Bench::Test::Remote}:

\begin{description}
\item[{\texttt{OUTPUTFILE:}}] \mbox{}

Es posible que el programa del usuario vuelque la
salida sobre un fichero en lugar de mostrarla por pantalla. Este parámetro indica
la ruta a dicho fichero.
\item[{\texttt{BASEDIR:}}] \mbox{}

Indica el directorio donde se almacenarán los resultados
de las ejecuciones cuando se utilice el script \texttt{createtests}
(Véase la documentación del script en el capítulo \ref{chapter:createtests}).

\end{description}

\section{Validez de los tests}

Cada ejecución realizada genera un campo llamado \texttt{TEST} que
indica si el test es válido (\textit{ok}) o no válido (\textit{Fail}).
El usuario puede indicar la condición de validez de un test mediante la
rutina \texttt{Bench::Test::Entry::is\_ok}. Esta rutina recibe como
parámetro el objeto de la clase \texttt{Bench::Test::Entry} asociado al
test en cuestión. Este objeto tiene disponibles todos los valores
de los campos definidos por el usuario en el array \texttt{@TABLE} y
algunos otros métodos muy útiles. Véase la documentación del módulo
\texttt{Bench::Test::Entry} en el capítulo \ref{chapter:Bench-Test-Entry}.

Un test se considera válido cuando la rutina \texttt{Bench::Test::Entry::is\_OK}
devuelve un valor verdadero. Si no fuera vital validar las ejecuciones, el usuario
podría escribir la rutina de forma que el resultado siempre fuese
válido:

\begin{verbatim}
   sub Bench::Test::Entry::is_OK {
      return 1;
   }
\end{verbatim}

En este caso se podría considerar que el resultado de una ejecución es válido
si se cumple que:

\begin{itemize}
\item Si el valor de beneficio óptimo obtenido (campo \texttt{OPT}) es el 
mismo que el que se obtuvo en una ejecución anterior que sirva como base.

\item Si el valor de beneficio óptimo (\texttt{OPT}) es mayor o igual que
el valor de beneficio heurístico (\texttt{HEUR}). El caso contrario sería
erróneo.
\end{itemize}

Por comodidad, y por no disponer de una primera versión \textit{estable} y
comprobada, se escogerá la segunda opción. La rutina quedaría así:

\newpage
\begin{verbatim}
   sub Bench::Test::Entry::is_OK { 
      my $entry = shift;

      my $opt = $self->get_field_value('OPT');
      my $heu = $self->get_field_value('HEUR');
 
      return $opt >= $heu;
   }
\end{verbatim}

La rutina anterior sigue estos pasos:

\begin{enumerate}
\item Recoge como parámetro el objeto \texttt{Bench::Test::Entry} asociado
a la ejecución en cuestión.
\item Recoge el valor del campo \texttt{OPT} gracias al método \texttt{get\_field\_value}.
\item Recoge el valor del campo \texttt{HEUR} gracias al método \texttt{get\_field\_value}.
\item Devuelve el resultado de la comprobación \texttt{OPT >= HEU}.
\end{enumerate}

\section{¿Qué campos mostrar?}

Es posible que en algún momento se necesite decidir si ver u ocultar alguno
de los campos que hemos especificado en el array \texttt{@TABLE}. Para
ello hacemos uso del array \texttt{@VISUAL}.

El array \texttt{@VISUAL} contiene una lista con los nombres de los
campos que queremos que aparezcan en la tabla final de resultados de la
siguiente tanda de ejecuciones. \texttt{@VISUAL} es un subconjunto de
los nombres de \texttt{@TABLE}. Véase un ejemplo:

\begin{verbatim}
   @VISUAL = (
              'TEST',
              'NAME',
              'GEN',
              'COMP',
              'OPT',
              'HEUR',
              'UPPER',
              'HTIME',
              'TIME',
              'RATE'
             );
\end{verbatim}

Otra forma más cómoda de escribir el array \texttt{@VISUAL} es
utilizar el operador \texttt{qw} de Perl:

\begin{verbatim}
   @VISUAL = qw(TEST NAME GEN COMP OPT HEUR UPPER HTIME TIME RATE);
\end{verbatim}

En este caso se estaría indicando que se desea mostrar
si el test es valido (\texttt{TEST}), el nombre del test (\texttt{NAME}), 
el número de nodos generados y computados (\texttt{GEN} y \texttt{COMP}), 
el valor de la solución óptima (\texttt{OPT}), el valor de la solución
heurística (\texttt{HEUR}), el valor de cota superior (\texttt{UPPER}),
el tiempo empleado por la heurística (\texttt{HTIME}), el tiempo del algoritmo
completo (\texttt{TIME}), y la \textit{tasa de acierto} de la heurística
respecto del algoritmo completo (\texttt{RATE}).

Además de indicar qué campos mostrar, el array \texttt{@VISUAL} es
usado para definir el orden en el que aparecerán dichos campos.

\section{Campos invariables}

Muchas veces ocurre que el valor de algunos campos es independiente
del lugar donde se realizan las ejecuciones. Para este caso, 
los valores de beneficio de la heurística y del algoritmo
completo, el valor de cota superior, y el número de nodos generados,
computados e insertados no varían con respecto a la máquina en
la que se ejecuta, ya que se trata del mismo algoritmo.

Para evitar que se muestren estos valores repetidos para cada una de
las máquinas, se incluyen dichos campos en el array \texttt{@UNIQUE}:

\begin{verbatim}
   @UNIQUE = qw(OPT HEUR UPPER GEN COMP INS RATE);
\end{verbatim}

Esto hace que en las tablas producidas durante la ejecución
sólo haya una columna \verb|OPT|, pese a que todas las ejecuciones
produzcan un campo \verb|OPT|.

Para ver la diferencia entre incluir o no incluir un campo
en el array \texttt{@UNIQUE}, se muestra un ejemplo:

Supongamos que el array \texttt{@VISUAL} está formado por
las claves \texttt{TEST}, \texttt{NAME} y  \texttt{OPT}:

\begin{verbatim}
   @VISUAL = qw(TEST NAME OPT);
\end{verbatim}

Si el campo \verb|OPT| se encuentra en el array \texttt{@UNIQUE},
la tabla de salida contendría un solo campo \texttt{OPT}:

\begin{verbatim}
   $ maketest
   TEST  NAME   OPT   
   ok    cut01  144   
   ok    cut02  244   
   ok    cut03  2778  
   ok    cut04  2892
   ok    cut05  2721
   ok    cut06  1860
\end{verbatim}

Si no se incluyese el campo \verb|OPT|, se generarían tres campos
llamados \verb|OPT(FEB_07)|, \verb|OPT(LOCAL)| y \verb|OPT(ORION)|,
aunque su valor sería el mismo:

\begin{verbatim}
   $ maketest
   TEST  NAME   OPT(FEB_07)  OPT(LOCAL)  OPT(ORION)  
   ok    cut01  144          144         144         
   ok    cut02  244          244         244         
   ok    cut03  2778         2778        2778        
   ok    cut04  2892         2892        2892        
   ok    cut05  2721         2721        2721        
   ok    cut06  1860         1860        1860        
\end{verbatim}

\section{¿En qué máquinas ejecutar?}

Al igual que con los campos filtrados y el array \texttt{@VISUAL}, también
sería deseable poder evitar que se realicen ejecuciones en ciertas máquinas aunque
estén definidas en el hash \texttt{\%EXPERIMENTS}.

Para ello, en
el array \texttt{@SELECTED} se indican los nombres de los \texttt{EXPERIMENTS}
en los que se desea relizar las ejecuciones. Por ejemplo:

\begin{verbatim}
   @SELECTED = qw(FEB_07 LOCAL ORION);
\end{verbatim}

Al incluir todos los \texttt{EXPERIMENTS}, se realizarán las ejecuciones en
todas las máquinas definidas anteriormente. Si se quisiese
no ejecutar en la máquina remota, el array \texttt{@SELECTED} tendría la
siguiente forma:

\begin{verbatim}
   @SELECTED = qw(FEB07 LOCAL);
\end{verbatim}

\section{Formato de salida}

Por último, sólo queda definir el formato de salida con el 
array \texttt{@OUTPUTFORMAT}. Véase un ejemplo:

\begin{verbatim}
   @OUTPUTFORMAT = (
      'text'          => 'output.txt',
      'html'          => 'output.html',
      'latex'         => 'output.tex',
      'xml'           => 'output.xml',
   );
\end{verbatim}

Se trata de un hash cuyas claves indican el formato en el
que se quiere la salida y cuyo valor especifica el fichero
a donde se debe enviar la salida con dicho formato. Si se deja
el valor en blanco la salida se muestra por pantalla.

Los formatos disponibles son \texttt{text} (texto plano), \texttt{xml},
\texttt{html} y \texttt{latex}. Además es posible que el usuario provea
un nuevo formato mediante la clave \texttt{file:fichero.tt} donde
\texttt{fichero.tt} es el nombre del fichero en el que el usuario
ha escrito su plantilla con Template Toolkit (Ver
documentación de Template Toolkit \cite{PerlTemplateToolkit}).

Para poder formatear la salida se debe esperar hasta que
se realice la última ejecución. Sin embargo,
se muestran por pantalla línea a línea los resultados de
cada ejecución formateados con simples tabuladores.

\newpage

\section{Fichero de configuración}

El fichero de configuración quedaría como sigue:

\begin{verbatim}
   @TABLE = (
     OPT    => 'Sequential\s+Solution\s+Value\s*=\s*(\d+)', 
     HEUR   => 'Heuristic = (\d+)', 
     UPPER  => 'Global Upper Bound: (\d+)',
     GEN    => 'Generated\s+nodes\s*:\s*(\d+)',
     COMP   => 'Computed\s+nodes\s*:\s*(\d+)',
     INS    => 'Inserted\s+nodes\s*:\s*(\d+)',
     HTIME  => 'Heuristic\s+Time:\s*(.*)\n',
     TIME   => '\nTime:\s*(.*)\n',
     RATE  => sub {
                 my $output = shift;
                 $output =~ /Heuristic = (.*)\n(.|\n)*Value = (.*)\n/;
                 my $rate = 100 * $1 / $3;
                 return "$rate\%";
              }
   );
\end{verbatim}

\begin{verbatim}
   @TESTS = (
     cut01 => 'tests/cut2D.1_.dat',
     cut02 => 'tests/cut2D.1.dat',
     cut03 => 'tests/cut2D.2_.dat',
     cut04 => 'tests/cut2D.2.dat',
     cut05 => 'tests/cut2D.3_.dat',
     cut06 => 'tests/cut2D.3.dat',
     cut07 => 'tests/cut2D.A1.dat',
     cut08 => 'tests/cut2D.A2.dat',
     cut09 => 'tests/cut2D.A3.dat',
     cut10 => 'tests/cut2D.A4.dat',
   );
\end{verbatim}

\begin{verbatim}
   sub my_preamble {
      my $machine = shift;
      $machine->put(['cutting.tar.gz']);
      $machine->tar('cutting.tar.gz', '-xz');
      $machine->chdir('cutting');
      $machine->system('make');
   };

   sub my_postamble {
      my $machine = shift;
      $machine->chdir('..');
      $machine->system('rm -rf cutting');
      $machine->system('rm cutting.tar.gz');
   }
\end{verbatim}

\begin{verbatim}
   %EXPERIMENTS = (
     'FEB_07' => Bench::Test::Base->new (
                    WORKDIR => 'FEB_07'
                 ),

     'LOCAL'  => Bench::Test::Local->new  (
                    WORKDIR   => '.',
                    EXECUTABLE => './cutting',
                 ),

     'ORION'  => Bench::Test::Remote->new (
                    HOST       => 'user@host',
                    WORKDIR    => '/home/user/cutting',
                    EXECUTABLE => 'cutting',
                    PREAMBLE   => \&my_preamble,
                    POSTAMBLE  => \&my_postamble,
                 ),
   );
\end{verbatim}

\begin{verbatim}
   sub Bench::Test::Entry::is_OK {
       my $self = shift;

       my $opt = $self->get_field_value('OPT');
       my $heu = $self->get_field_value('HEUR');
 
      return $opt > $heu;
   }
\end{verbatim}

\begin{verbatim}
   @VISUAL   = qw(TEST NAME GEN COMP OPT HEUR UPPER HTIME TIME RATE);
   @UNIQUE   = qw(OPT HEUR UPPER GEN COMP INS RATE);
   @SELECTED = qw(FEB_07 LOCAL ORION);
\end{verbatim}

\begin{verbatim}
   @OUTPUTFORMAT = (
      'text'          => 'output.txt',
      'html'          => 'output.html',
      'latex'         => 'output.tex',
      'xml'           => 'output.xml',
   );
\end{verbatim}

\newpage

\section{Resultado}

Para mayor comodidad supongamos que en el fichero de configuración
se han definido los arrays \texttt{@VISUAL} y \texttt{@SELECTED} de
la siguiente forma:

\begin{verbatim}
   @VISUAL   = qw(TEST NAME RATE TIME);
   @SELECTED = qw(LOCAL ORION);
\end{verbatim}

De esta forma se muestra información sobre el tiempo de ejecución
y de la tasa de acercamiento de la heurística respecto del
algoritmo completo. Además, solo se comparan las ejecuciones
en máquina local y en la máquina remota \verb|ORION|.

Gracias a esta reducción del número de campos que se visualizan
y de las máquinas en donde se llevan a cabo las ejecuciones 
se obtendrán tablas de datos más cortas y se podrá apreciar con más
detalle todos los formatos en los que se obtiene la salida.

Una ejecución del script \texttt{maketest} con el fichero de configuración
anteriormente descrito daría como resultado algo como:

\begin{small}
\begin{verbatim}
   $ maketest 
   TEST    NAME    RATE(LOCAL)     RATE(ORION)  TIME(LOCAL)  TIME(ORION)
   ok      cut01    97.2%   97.2%  0.386975     0.251727
   ok      cut02    98.4%   98.4%  0.001214     0.000458
   ok      cut03   100.0%  100.0%  0.007742     0.005901
   ok      cut04   100.0%  100.0%  0.028823     0.021571
   ok      cut05   100.0%  100.0%  0.000069     0.000071
   ok      cut06    98.9%   98.9%  0.385762     0.245468
   ok      cut07    95.0%   95.0%  0.086240     0.151367
   ok      cut08    97.2%   97.2%  7.338252     5.606661
   ok      cut09   100.0%  100.0%  0.054635     0.045010
   ok      cut10    99.0%   99.0%  0.161601     0.136388
\end{verbatim}
\end{small}

Esta tabla se va generando línea a línea, ejecución tras ejecución,
para que el usuario disponga de una respuesta rápida, aunque sea
sin formato.

Los demás formatos son volcados sobre los distintos ficheros
especificados en el array \texttt{@OUTPUTFORMAT}.

\subsection{Formato \texttt{text}}

Es el formato más simple de los cuatro formatos disponibles.
Devuelve los resultados como texto plano correctamente alineados.
Puede ser muy útil para trabajar con paquetes matemáticos
como \textbf{Octave} \cite{octave} o \textbf{Matlab} \cite{matlab},
o el paquete estadístico \textbf{R} \cite{R}.

El contenido del fichero \texttt{output.txt} obtenido de las ejecuciones
anteriores es el siguiente:


\begin{small}
\begin{verbatim}
   $ cat output.txt
   TEST  NAME   RATE    TIME(LOCAL)  TIME(ORION)  
   ok    cut01   97.2%  0.386975     0.251727     
   ok    cut02   98.4%  0.001214     0.000458     
   ok    cut03  100.0%  0.007742     0.005901     
   ok    cut04  100.0%  0.028823     0.021571     
   ok    cut05  100.0%  0.000069     0.000071     
   ok    cut06   98.9%  0.385762     0.245468     
   ok    cut07   95.0%  0.086240     0.151367     
   ok    cut08   97.2%  7.338252     5.606661     
   ok    cut09  100.0%  0.054635     0.045010     
   ok    cut10   99.0%  0.161601     0.136388     
\end{verbatim}
\end{small}

\subsection{Formato \texttt{xml}}

\textbf{XML} no nació sólo para su aplicación en Internet, sino que se propone como un estándar para
el intercambio de información estructurada entre diferentes plataformas. Se puede usar en bases
de datos, editores de texto, hojas de cálculo y casi cualquier cosa imaginable. Es por ello que
podría ser muy útil guardar los datos con este formato.

La estructura de formato que se propone consta de un elemento raiz \texttt{data} que contiene
un elemento \texttt{entry} por cada ejecución realizada. La información asociada a dichas ejecuciones se
guarda en atributos cuyos nombres coinciden con el nombre de los campos generados. Véase
el resultado de las ejecuciones anteriores en formato XML:

\begin{tiny}
\begin{verbatim}
   $ cat output.xml
   <?xml version="1.0" encoding="ISO-8859-1" ?>
   <data>
      <entry test="ok" name="cut01" rate=" 97.2%" time_local="0.386975" time_orion="0.251727" />
      <entry test="ok" name="cut02" rate=" 98.4%" time_local="0.001214" time_orion="0.000458" />
      <entry test="ok" name="cut03" rate="100.0%" time_local="0.007742" time_orion="0.005901" />
      <entry test="ok" name="cut04" rate="100.0%" time_local="0.028823" time_orion="0.021571" />
      <entry test="ok" name="cut05" rate="100.0%" time_local="0.000069" time_orion="0.000071" />
      <entry test="ok" name="cut06" rate=" 98.9%" time_local="0.385762" time_orion="0.245468" />
      <entry test="ok" name="cut07" rate=" 95.0%" time_local="0.086240" time_orion="0.151367" />
      <entry test="ok" name="cut08" rate=" 97.2%" time_local="7.338252" time_orion="5.606661" />
      <entry test="ok" name="cut09" rate="100.0%" time_local="0.054635" time_orion="0.045010" />
      <entry test="ok" name="cut10" rate=" 99.0%" time_local="0.161601" time_orion="0.136388" />
      <entry test="ok" name="cut11" rate="100.0%" time_local="1.128277" time_orion="0.879753" />
      <entry test="ok" name="cut12" rate=" 92.7%" time_local="0.129981" time_orion="0.142284" />
   </data>
\end{verbatim}
\end{tiny}

\subsection{Formato \texttt{html}}

El formato \textbf{HTML} puede ser útil si el trabajo que se está realizando ha
de ser publicado en Internet. En la figura~\ref{fig:outputhtml2} se muestra
el contenido del fichero \texttt{output.html} abierto en un navegador.

\begin{figure}{h!}
  \centering
    \includegraphics[width=\textwidth]{images/outputhtml2.png}
  \caption{Salida en formato HTML vista en un navegador}
  \label{fig:outputhtml2}
\end{figure}

\subsection{Formato \texttt{latex}}

Para un investigador es muy útil obtener los resultados en formato \textbf{\LaTeX}
de forma que sea instantánea la inclusión de dichos resultados en el próximo
artículo que esté escribiendo. Para ello bastaría con incluir en su
fichero \texttt{.tex} una línea con la orden: \verb!\input{output.tex}!.

Y tendría automáticamente incluída una tabla final de datos como la mostrada
en el cuadro~\ref{table:outputlatex}.

\begin{table}
\begin{center}
\begin{tabular}{|ccccc|}
\hline
TEST & NAME & RATE & TIME(LOCAL) & TIME(ORION)\\
\hline
ok & cut01 &  97.2\% &  0.386975 & 0.251727\\
\hline
ok & cut02 &  98.4\% &  0.001214 & 0.000458\\
\hline
ok & cut03 & 100.0\% &  0.007742 & 0.005901\\
\hline
ok & cut04 & 100.0\% &  0.028823 & 0.021571\\
\hline
ok & cut05 & 100.0\% &  0.000069 & 0.000071\\
\hline
ok & cut06 &  98.9\% &  0.385762 & 0.245468\\
\hline
ok & cut07 &  95.0\% &  0.086240 & 0.151367\\
\hline
ok & cut08 &  97.2\% &  7.338252 & 5.606661\\
\hline
ok & cut09 & 100.0\% &  0.054635 & 0.045010\\
\hline
ok & cut10 &  99.0\% &  0.161601 & 0.136388\\
\hline
\end{tabular}
\end{center}
\caption{Tabla generada con \texttt{Bench::Test}}
\label{table:outputlatex}
\end{table}

\newpage

\subsection{Otros formatos: el formato \texttt{file}}

Si los cuatro formatos anteriores no son suficiente o se desea personalizar
aún más la salida, el usuario tiene la posibilidad de escribir una plantilla
utilizando Template Toolkit \cite{TT}. La forma de especificar la nueva plantilla
es, como se mencionó antes, la siguiente:

\begin{verbatim}
   @OUTPUTFORMAT = (
      'file:miplantilla.tt' => 'outputfile'
   );
\end{verbatim}

El único aspecto que debe conocer el usuario al escribir la plantilla es que
los datos se encuentran en la variable \texttt{data} y que dicha variable se trata de un
\textit{array de arrays} que contiene todos los valores
obtenidos en las ejecuciones.

Véase un ejemplo de plantilla:

\begin{verbatim}
   $ cat miplantilla.tt 
   [% FOREACH row IN data -%]
   Row: [ 
   [%- FOREACH item IN row -%]$item [%- END -%]
   ]
   [% END -%]
\end{verbatim}

Con esta plantilla se obtendría un resultado como este:

\begin{verbatim}
   $ cat outputfile
   Row: [ TEST NAME RATE TIME(LOCAL) TIME(ORION) ]
   Row: [ ok cut01  97.2% 0.390414 0.309255 ]
   Row: [ ok cut02  98.4% 0.001208 0.000451 ]
   Row: [ ok cut03 100.0% 0.012183 0.005965 ]
   Row: [ ok cut04 100.0% 0.028402 0.021579 ]
   Row: [ ok cut05 100.0% 0.000063 0.000066 ]
   Row: [ ok cut06  98.9% 0.308219 0.246017 ]
   Row: [ ok cut07  95.0% 0.086591 0.069746 ]
   Row: [ ok cut08  97.2% 7.176788 8.776497 ]
   Row: [ ok cut09 100.0% 0.055091 0.045222 ]
   Row: [ ok cut10  99.0% 0.161295 0.137805 ]
\end{verbatim}
\section{Decisiones}

Las dos primeras decisiones que se tomaron al comenzar el proyecto
fueron el lenguaje de programación a utilizar y la plataforma sobre la que se 
implementaría. No fue una tarea dificil tomar dichas decisiones:

\begin{itemize}
\item
Plataforma \textbf{Unix/Linux}
\item
Lenguaje de programación \textbf{Perl}
\end{itemize}

\subsection{¿Por qué Unix/Linux?}

Le experiencia nos muestra que la gran mayoría de los usuarios a los que
va destinada nuestra herramienta, desarrolla sus proyectos en entornos
Unix/Linux utilizando lenguajes como C, C++ o FORTRAN.

Por otro lado, existen entornos como \textit{Cygwin} que permiten
portar software que se ejecuta en sistemas \textit{POSIX} a sistemas 
\textit{Windows}. Es por ello que se ha escogido la plataforma 
\textbf{Unix/Linux} para el desarrollo de este proyecto.

\subsection{¿Por qué Perl?}

Como su nombre indica, \textbf{Perl} (\textit{Practical Extraction and Report Language})
es un lenguaje de propósito general originalmente desarrollado para
la manipulación de texto y que ahora es utilizado para un amplio rango
de tareas, incluyendo administración de sistemas, desarrollo web,
programación en red y desarrollo de iterfaces de usuario (\textit{GUI}).

Se previó que fuera práctico (facilidad de uso, eficiente y completo)
en lugar de hermoso (pequeño, elegante y mínimo). Sus principales
características son la facilidad de uso, el soporte para programación
estructurada, programación orientada a objetos y programación
funcional. Además, tiene incorporado un poderoso sistema de
procesamiento de texto basado en expresiones regulares y dispone de
un enorme repositorio mundial, conocido como \textbf{CPAN} (\textit{Comprehensive
Perl Archive Network}), en donde programadores de todo el mundo 
comparten su trabajo.

Otra gran virtud de \textbf{Perl} es que viene incluido en la gran mayoría
de las distribuciones Unix/Linux actuales. Por otro lado, también
dispone de versiones para sistemas \textbf{Microsoft} y \textbf{MacOS} entre otros.

Como se verá durante el desarrollo de esta memoria, estas
características se ajustan perfectamente a las necesidades de
este proyecto:

\begin{itemize}
\item
Programación orientada a objetos.
\item
Ejecución en máquina local y máquinas remotas.
\item
Manipulación de textos y filtrado mediante expresiones regulares.
\item
Elaboración de informes en distintos formatos.
\end{itemize}

\section{Diagrama de clases}

Durante el desarrollo de la herramienta \texttt{Bench::Test} se ha
intentado seguir un diseño \textbf{MVC} (Modelo Vista Controlador) 
haciendo uso del paradigma de programación orientada a objetos 
separando el acceso a datos, y el procesamiento de los mismos, de la
presentación al usuario.

El acceso a datos, en este caso las salidas resultado de las
ejecuciones, se realiza mediante tres clases en las que se
basa el mecanismo de ejecución de los tests:
\texttt{Bench::Test::Base}, \texttt{Bench::Test::Local} y
\texttt{Bench::Test::Remote}. Cuando el acceso es a los resultados
de ejecuciones anteriores se utiliza la primera, para ejecuciones en
máquina local, la segunda, y para ejecuciones en máquinas remotas,
la tercera. Este acceso se realiza invocando al método \texttt{get\_result} de
la clase en cuestión.

A medida que se realizan las ejecuciones, la clase
\texttt{Bench::Test::View} va recolectando los resultados
para posteriormente darles el formato correspondiente y
presentarle al usuario una visión formateada de los mismos.

\begin{figure}
  \centering
    \includegraphics[width=\textwidth]{images/classdiagram.png}
  \caption{Diagrama de clases}
  \label{fig:classdiagram}
\end{figure}

En la figura \ref{fig:classdiagram} se muestra el
diagrama de clases asociado al proyecto.

\section{Diagrama de secuencia}

En la figura~\ref{fig:seqdiagram} se muestra el diagrama de
secuencia asociado a la ejecución de cada uno de los tests.

%\clearpage

\begin{figure}
  \centering
   \includegraphics[width=\textwidth]{images/seqdiagram.png}
  \caption{Diagrama de secuencia para la ejecución de un test}
  \label{fig:seqdiagram}
\end{figure}

El objeto \texttt{Bench::Test} invoca el método \texttt{get\_result} de cada
uno de los objetos \texttt{Bench::Test::Base}, \texttt{Bench::Test::Local} y
\texttt{Bench::Test::Remote} de que dispone y cuando ha obtenido de todos los
resultados envía una fila de datos al objeto \texttt{Bench::Test::View}
(invocando el método \texttt{add\_row}) que se encargará de
almacenarla. Una vez finalizados todos los tests, se podrá acceder
al resultado correctamente formateada mediante una llamada al método
\texttt{process} indicándo el formato deseado en su parámetro
\texttt{format}.

\section{Modelo Vista Controlador}

Para la realización de este proyecto se ha intentado hacer una pequeña
aproximación al \textit{Modelo Vista Controlador}. Sin embargo, algunos
aspectos de este modelo quedan fuera del alcance de \texttt{Bench::Test}
puesto que no se cuenta con una interfaz gráfica que permita al usuario
interactuar con el sistema. A continuación se hace una breve introducción
al modelo.

Modelo Vista Controlador (\textit{MVC}) es un patrón de arquitectura de software
que separa los datos de una aplicación, la interfaz de usuario, y la lógica
de control en tres componentes distintos. Aunque el patrón \textbf{MVC} se ve
frecuentemente en aplicaciones web, donde la vista es la página HTML y el código
que provee de datos dinámicos a la página, también puede ser aplicado a muchos
otros tipos de aplicaciones.

\begin{description}

\item[{\textbf{Modelo:}}] \mbox{}

Ésta es la representación específica del dominio de la información sobre la
cual funciona la aplicación. El modelo es otra forma de llamar a la capa de
dominio. La lógica de dominio añade significado a los datos; por ejemplo,
calculando si hoy es el cumpleaños del usuario o los totales, impuestos o
portes en un carrito de la compra.

\item[{\textbf{Vista:}}] \mbox{}

Ésta presenta el modelo en un formato adecuado para interactuar, usualmente
un elemento de interfaz de usuario.

\item[{\textbf{Controlador:}}] \mbox{}

Éste responde a eventos, usualmente acciones del usuario e invoca cambios
en el modelo y probablemente en la vista.

\end{description}

Es común pensar que una aplicación tiene tres capas principales: presentación,
dominio, y acceso a datos. En \textbf{MVC}, la capa de presentación está partida
en controlador y vista. La principal separación es entre presentación y
dominio; la separación entre V/C es menos clara.

Aunque se pueden encontrar diferentes implementaciones de \textbf{MVC}, el flujo que
sigue el control generalmente es el siguiente:

\begin{enumerate}
\item
El usuario interactúa con la interfaz de usuario de alguna forma
(por ejemplo, pulsando un botón o especificando alguna entrada).
\item
El controlador recibe (por parte de los objetos de la interfaz-vista) la
notificación de la acción solicitada por el usuario. El controlador gestiona
el evento que llega, frecuentemente a través de un gestor de eventos (handler)
o callback.
\item
El controlador accede al modelo, actualizándolo, posiblemente modificándolo
de forma adecuada a la acción solicitada por el usuario (por ejemplo, el
controlador actualiza el carro de la compra del usuario). Los controladores
complejos están a menudo estructurados usando un patrón de comando que
encapsula las acciones y simplifica su extensión.
\item
El controlador delega a los objetos de la vista la tarea de desplegar la
interfaz de usuario. La vista obtiene sus datos del modelo para generar
la interfaz apropiada para el usuario donde se refleja los cambios en el
modelo (por ejemplo, produce un listado del contenido del carro de la compra).
El modelo no debe tener conocimiento directo sobre la vista. Sin embargo,
el patrón de observador puede ser utilizado para proveer cierta indirección
entre el modelo y la vista, permitiendo al modelo notificar a los interesados
de cualquier cambio. Un objeto vista puede registrarse con el modelo y esperar
a los cambios, pero aun así el modelo en sí mismo sigue sin saber nada de la
vista. El controlador no pasa objetos de dominio (el modelo) a la vista aunque
puede dar la orden a la vista para que se actualice.
\item
La interfaz de usuario espera nuevas interacciones del usuario, comenzando
el ciclo nuevamente.
\end{enumerate}
\section{Nombre}

\texttt{Bench::Test::Entry}

Almacena los resultados de una ejecución clasificados por campos

\section{Sinopsis}

\begin{verbatim}
   my $entry = Bench::Test::Entry->new(
      FIELDS    => \@fields,
      EXP_NAMES => \@exp_names,
      UNIQUE    => \@unique, 
   );
\end{verbatim}
\begin{verbatim}
   $entry->set_test_field;
   $entry->set_name_field;
\end{verbatim}
\begin{verbatim}
   $entry->get_field_value('OPT');
   $entry->get_field_value('TIME', 'ORION');
\end{verbatim}

\section{Descripción}


El objeto \texttt{Bench::Test::Entry} sirve como almacén de los 
resultados obtenidos en una ejecución, ya sea en máquina
local o en máquina remota.

Dispone de métodos para establecer u obtener dichos 
valores.

\section{Métodos}

\subsection{El constructor \texttt{new}}

El constructor acepta los siguientes parámetros:

\begin{description}

\item[{\texttt{FIELDS}}] \mbox{}

Referencia a un array que contiene los nombres de los campos
para los que se almacenarán sus valores

\item[{\texttt{EXP\_NAMES}}] \mbox{}

Referencia a un array que contiene los nombres de las máquinas
donde se realizarán la sejecuciones.

\item[{\texttt{UNIQUE}}] \mbox{}

Referencia a un array que contiene los campos cuyo
valor es independiente de la máquina en la que se
ejecuta.

\end{description}

\subsection{Los métodos \texttt{get\_field\_value} y \texttt{set\_field\_value}}

Véase unos ejemplos:

\begin{verbatim}
   $entry->set_field_value('TIME', 'ORION', '0.123');
   $entry->get_field_value('TIME', 'ORION');
   $entry->get_field_value('OPT');
\end{verbatim}

La primera llamada establece el valor del campo \texttt{TIME} para
la máquina \texttt{ORION}. La segunda obtiene ese valor. Y la 
tercera obtiene el valor del campo \texttt{OPT}. Si suponemos
que el valor de dicho campo no depende de la máquina donde
se ejecuta, ésta no hace falta especificarla.

\subsection{Los métodos \texttt{set\_test\_field} y \texttt{set\_name\_field}}

El método \texttt{set\_test\_field} ejecuta la rutina \texttt{is\_OK} que
debe haber sido definida previamente por el usuario para 
indicar si un test es válido o no. Dependiendo del resultado
de la llamada, establece el valor del campo \texttt{TEST} a \texttt{ok}
o \texttt{Fail}.

El método \texttt{set\_name\_field} recibe como parámetro el nombre
del test asociado a la ejecución actual y establece el
valor del campo \texttt{NAME}.

\section{Véase también}

Para una mejor comprensión del módulo \texttt{Bench::Test::Entry},
véase también la documentación de los siguientes módulos:

\begin{itemize}
\item \texttt{Bench::Test}
\end{itemize}
Una vez realizado el diseño de la herramienta \texttt{Bench::Test} se
da paso a su implementación. Como en todos los proyectos, en esta etapa 
surgen dificultades y se debe hacer frente a la toma
de decisiones que afectarán directamente al resultado final.

A continuación se analizan todos los aspectos relacionados con la etapa
de implementación (dificultades, requisitos, decisiones) sin entrar en
detalles los detalles de bajo nivel (codificación).

\section{Requisitos}

El primer paso antes de empezar la codificación es definir cuáles serán
los requisitos que se impondrán al usuario final para la utilización
de \texttt{Bench::Test}.
Idealmente se debería conseguir que estos
requisitos no sean muy numerosos y si es posible, evitarlos.

\subsection{Requisitos del programa cliente}

El módulo \texttt{Bench::Test} trabaja programando ejecuciones en
distintas máquinas y filtrando las salida para obtener los valores
que realmente importan. Es por ello que el primer requisito que se
le impone al usuario es la \textit{instrumentación} de su programa,
de forma que su salida contenga \textbf{todos} los valores que puedan
tener interés (tiempo, tamaño del problema, \dots).

Como la salida será filtrada mediante expresiones regulares, sería
recomendable tener un formato que facilite la extracción de los valores
utilizando dichas expresiones regulares que el mismo usuario deberá definir.

A continuación se muestra un ejemplo de cómo podría ser la
salida de un programa correctamente instrumentado:

\newpage

\begin{verbatim}
   $ ./main.seq tests/cut2D.3.dat 
   Heuristic: 1840
   Heuristic Time: 0.039420
   Problem Name: tests/cut2D.3.dat
   Global Upper Bound: 2240
   Computed nodes: 1173
   Generated nodes: 1442
   Time: 0.371814
   Sequential Solution Value: 1860
\end{verbatim}

Puede pensarse que la instrumentación del programa es algo 
trivial, pero no es así. A continuación se muestra una salida
del mismo programa \textit{mal instrumentado}. En este caso
es difícil (que no imposible) obtener los parámetros mediante
expresiones regulares:

\begin{verbatim}
   $ ./main.seq tests/cut2D.3.dat
   Problem Name       Heuristic  H.Time    Seq.Solution  Time
   tests/cut2D.3.dat  1840       0.039420  1860          0.371814
\end{verbatim}

\subsection{Requisitos de la máquina}

Como ya se ha comentado, la herramienta \texttt{Bench::Test} permite
programar ejecuciones en máquinas remotas. Para ello se hace uso del 
módulo \texttt{GRID::Machine} \cite{CasianoGridMachineDoc}. 

El módulo \texttt{GRID::Machine} permite realizar llamadas a procedimientos
remotos (\textit{RPC}) mediante un enlace \textbf{SSH}. Para que ésto sea 
posible se debe tener acceso automático sin contraseña a cada una de las
máquinas sobre las que se desea lanzar las ejecuciones. (véase el apéndice
``\textit{Login SSH automático}'' del capítulo \ref{chapter:ssh}).

\subsection{Interfaz de usuario ¿Cómo se usa?}

Una vez diseñadas las interfaces entre objetos, sólo resta definir
la forma en la que el usuario define los parámetros que permiten
guiar las ejecuciones.

En principio, el usuario debe escribir un script Perl que cree un objeto
de la clase \texttt{Bench::Test} pasando al constructor todos
y cada uno de los parámetros que guían las ejecuciones. A continuación se
debe invocar alguno de los métodos (\texttt{make\_test} o \texttt{create\_test})
que llevan a cabo las ejecuciones para mostrar los resultados al usuario,
o para almacenar los resultados respectivamente (véase la documentación
del módulo \texttt{Bench::Test} en el capítulo \ref{chapter:Bench-Test}).

Este proceso, aunque sencillo, requiere del usuario un mínimo de
conocimiento de la sintaxis del lenguaje Perl para 
cargar los módulos necesarios, crear un objeto, e invocar métodos.

No todo el mundo es amante del lenguaje Perl, así que para evitar
lo máximo posible la escritura de código Perl por
parte del usuario se decidió crear dos pequeños scripts que realizaran
las tareas descritas. El nombre de estos scripts es \texttt{maketest} y
\texttt{createtest} y se encuentran disponible dentro de la carpeta
\texttt{/script} de la distribución (véase la documentación de dichos
scripts en los capítulos \ref{chapter:maketest} y \ref{chapter:createtests}).

Gracias a estos dos scripts, el usuario se
desentiende de la creación del objeto. La forma
que tiene de definir los parámetros correspondientes es mediante
la escritura de un fichero de configuración cuyo nombre por defecto
es \texttt{maketest.conf}. Más adelante en esta memoria se detallará
el contenido de dicho fichero de configuración.

Para aquellos usuarios que la escritura de dicho fichero de
configuración les suponga un obstáculo muy grande por estar escrito con
sintaxis Perl, se provee otro script (\texttt{configcreate}) que
automatiza este proceso sin necesidad de escribir código Perl
(véase la documentación del script \texttt{configcreate} en el
capítulo \ref{chapter:configcreate}).

\section{Dependencias}

El módulo \texttt{Bench::Test} necesita la instalación de otros módulos
para funcionar correctamente. Los módulos necesarios son:

\begin{itemize}
\item \texttt{GRID::Machine}
\item \texttt{Template}
\item \texttt{Storable}
\end{itemize}

El módulo \texttt{Storable} viene ya instalado con la distribución de
Perl, pero los módulos \texttt{GRID::Machine} y \texttt{Template} han
de ser instalados por el usuario (véase el apéndice
``\textit{CPAN. Instalación de módulos}'' en el capítulo
\ref{chapter:cpan})

\section{Almacenamiento del resultado de las ejecuciones}

El módulo \texttt{Bench::Test::Base} permite acceder a los resultados de
ejecuciones realizadas en el pasado que se quisieron almacenar. Ante la
forma de almacenar estos datos puede surgir una duda.
¿Almacenar la salida intacta o almacenar la salida filtrada?  Cualquiera
de las opciones tiene sus ventajas e inconvenientes.

En un primer momento se podría pensar que almacenando la salida filtrada
se ahorra tiempo cada vez que se accede a ella puesto que no debe
filtrarse una y otra vez. Sin embargo, es posible que el usuario cuando
realiza las ejecuciones no esté interesado en ciertos parámetros que en
el futuro sí podrían ser útiles. Si se almacena la salida filtrada, estos
parámetros se pierden para siempre.

Por ello, las salidas de las ejecuciones son almacenadas \textbf{intactas}
de forma que no se pierda ninguna información que pueda ser útil, sobretodo,
en el futuro.

Además, el procesado de la salida del programa (recuérdese que se trata de
texto plano) no es una operación costosa, así que la posible ganancia de almacenar
la salida filtrada no es tanta en comparación con los más que probables
inconvenientes.

\section{Dificultades}

Las mayores dificultades encontradas durante la etapa de implementación
fueron las relacionadas con la depuración de errores. Como se dijo en
la introducción, el lenguaje \textbf{Perl} es un lenguaje muy potente,
pero muy \textit{permisivo}.

La carencia de un conjunto generoso de tipos de datos y el hecho de ser
un lenguaje interpretado provoca que, en muchas ocasiones, un error
de codificación no sea detectado hasta que una prueba en concreto lo
delata.

Si a esto se suma la posibilidad de que el error provenga de algún
conflicto con los permisos (permisos, variables de entorno, etc.)
en cualquiera de las máquinas remotas donde se están realizando
las ejecuciones, el panorama se presenta verdaderamente complicado. 

\section{Introducción}

Como todo proyecto, \texttt{Bench::Test} nace a raíz de una
necesidad de un colectivo que ha de ser satisfecha. El trabajo
de un investigador en el campo de la informática en general,
y de la algoritmia en particular, es duro, difícil y, en muchas
ocasiones, repetitivo. El diseño de nuevos algoritmos o 
la modificación y optimización de algoritmos ya conocidos,
están a la orden del día para un investigador en este
sector.

Casi tan importante como el diseño y la implementación
de un algoritmo, es su documentación y la creación de un
generoso conjunto de pruebas que permitan comprobar tanto
la validez, como la eficiencia del mismo.

Actualmente existen muchas herramientas que permiten la
planificación de ejecuciones por lotes. La mayoría de ellas
se ven limitadas a ejecuciones secuenciales en la máquina
local sin ningún tipo de postprocesamiento ni formateo
de los resultados. Cubrir estas limitaciones ha sido
el objetivo principal de este proyecto.

\section{Objetivos}

En un principio el paquete \texttt{Bench::Test} fue ideado
como herramienta que permitiera al usuario recibir una
respuesta rápida (\textit{fast feedback}) de los resultados
que obtenía su proyecto/algoritmo frente a un
conjunto determinado de pruebas. Finalmente,
el módulo que se presenta en esta memoria ha ido ganando
funcionalidades poco a poco hasta terminar convirtiéndose
en una potente herramienta cuya flexibilidad pone en las
manos del usuario un sin fin de posibilidades. Por ejemplo:

\begin{itemize}
\item 
Comparar el rendimiento de un algoritmo frente a otro. Para
ello se define un conjunto de pruebas variadas y se programan
ejecuciones con cada uno de los algoritmos a comparar.
\item 
Comparar el rendimiento de mdiferentes máquinas. Se establece
un mismo algoritmo (o varios) y se ejecutan sobre las
máquinas que se desea comparar.
\item
Comparar los resultados a través del tiempo. El usuario puede
necesitar comparar los resultados de su algoritmo en el
estado actual con los resultados obtenidos en versiones
anteriores.
\item
Ofrecer al usuario no sólo una respuesta rápida, sino darle
la posibilidad de obtener los resultados en formatos tan
extendidos como XML, HTML y Latex, entre otros.
\end{itemize}

Éstos y otros objetivos han sido plenamente cubiertos durante
el desarrollo de este proyecto.
\section{Nombre}

\texttt{Bench::Test::Local}

Automatiza ejecuciones en la máquina local

\section{Sinopsis}

\begin{verbatim}
   my $local = Bench::Test::Local->new(
      WORKDIR   => '.',
      EXECUTABLE => './mm',
      OUTPUTFILE => 'output.dat',
      BASEDIR   => './base_FEB',
   );
\end{verbatim}
\begin{verbatim}
   my $parameters = ...
   my $output = $local->get_result($parameters);
\end{verbatim}
\begin{verbatim}
   $local->save_result($parameters, $testname);
\end{verbatim}

\section{Descripción}

El objeto \texttt{Bench::Test::Local} permite encapsular la operación
de ejecución de programas en la máquina local. Dispone de dos
métodos que permiten obtener la salida de la ejecución o almacenarla
respectivamente: \texttt{get\_result} y \texttt{save\_result}

\subsection{Un ejemplo}

Supongamos un programa cuya salida sea la siguiente:

\begin{verbatim}
  ~/projects/Bench-Test/examples/mm$ ./mm dat/mm_200.dat 
  Filas primera matriz: 200
  Filas segunda matriz: 200
  Columnas segunda matriz: 200
  Time of product: 0.210942
  Result: 4102
\end{verbatim}

Creamos un objeto \texttt{Bench::Test::Local} de la siguiente forma:

\begin{verbatim}
   my $local = Bench::Test::Local->new(
      WORKDIR   => '.',
      EXECUTABLE => './mm',
   );
\end{verbatim}

Con una llamada a \texttt{get\_result} como la que sigue:

\begin{verbatim}
   my $output = $local->get_result('dat/mm_200');
\end{verbatim}

Obtendríamos en \texttt{\$output} una salida similar. En cambio,
con una llamada a \texttt{save\_result} como esta:

\begin{verbatim}
   $local->save_result('dat/mm_200', 'test200');
\end{verbatim}

La salida del programa sería almacenada en el fichero
\texttt{test200.base}.

\section{Métodos}
\subsection{El constructor \texttt{new}}

Véase una llamada típica:

\begin{verbatim}
  my $local = Bench::Test::Local->new(
      WORKDIR   => '.',
      EXECUTABLE => './mm',
  );
\end{verbatim}

El constructor acepta los siguientes parámetros:

\begin{description}

\item[{\texttt{WORKDIR:}}] \mbox{}

Directorio de trabajo donde se encuentra 
el ejecutable y desde donde se llevarán a cabo todas las ejecuciones.

\item[{\texttt{EXECUTABLE:}}] \mbox{}

Nombre del fichero ejecutable.

\item[{\texttt{OUTPUTFILE:}}] \mbox{}

Parámetro opcional que indica el nombre del fichero
donde se encuentra la salida de la ejecucion del programa. Se
utiliza cuando el programa vuelca la salida en un fichero
en lugar de enviarla a la pantalla.

\item[{\texttt{BASEDIR:}}] \mbox{}

Nombre del directorio donde se creará el fichero \texttt{.base}
generado como consecuencia de la llamada a \texttt{save\_result}.

\item[{\texttt{GET\_RESULT} y \texttt{SAVE\_RESULT:}}] \mbox{}

Referencia a rutinas que serán llamadas
en lugar de \texttt{get\_result} y \texttt{save\_result}. Permite al usuario cambiar
el comportamiento por defecto de dichas rutinas.

\end{description}

\subsection{El método \texttt{get\_result}}

Véase una llamada típica:

\begin{verbatim}
   my $parameters = '-n 20 -p';
   my $output = $local->get_result($parameters);
\end{verbatim}

El método \texttt{get\_result} acepta como único parámetro una cadena que
indica los parámetros con los que se ejecutara el experimento
indicado en el constructor con el parámetro \texttt{EXECUTABLE}.

\subsection{El método \texttt{save\_result}}

Véase una llamada típica:

\begin{verbatim}
   $local->save_result($parameters, $testname);
\end{verbatim}

El método \texttt{save\_result} acepta igual que \texttt{get\_result} una
cadena de caracteres con los parámetros de ejecución para el ejecutable
definido con \texttt{EXECUTABLE} y el nombre del test correspondiente.

El método \texttt{save\_result} automatiza la ejecución invocando
al método \texttt{get\_result} y guardando la salida en un fichero
de texto ubicado en el directorio definido en el constructor
en el parámetro \texttt{BASEDIR}. El nombre del archivo se
obtiene concatenando el parámetro \texttt{\$testname} con la
extension \texttt{.base}.

\section{Véase también}

Para una mejor comprensión del módulo \texttt{Bench::Test::Local},
véase también la documentación de los siguientes módulos:

\begin{itemize}
\item \texttt{Bench::Test}
\item \texttt{Bench::Test::Base}
\item \texttt{Bench::Test::Remote}
\end{itemize}
\section{El módulo}

El módulo \texttt{GRID::Machine} es un módulo
escrito por {\bf Casiano Rodríguez León} \cite{CasianoGridMachineDoc}
que provee \textit{Remote Procedure Calls} o llamadas a procedimientos
remotos (RPC) a través de un enlace SSH.

Para su utilización deben poderse establecer autenticaciones
SSH automáticas entre la máquina local y las máquinas remotas
en donde se desee trabajar.

Las características principales de este módulo son:

\begin{itemize}
\item
\textit{Remote Procedure Calls} (RPC). Rutinas 
en el lado remoto pueden ser llamadas con estructuras
de datos arbitrariamente complejas como argumentos
desde el lado local.

\item
El resultado de una llamada remota es un objeto de
la clase \texttt{GRID::Machine::Result}. Entre sus
atributos se encuentran el resultado de la llamada
(\texttt{result}), la salida producida en \texttt{stdout}
y \texttt{stderr}.

\item
Servicios para la transferencia de ficheros.

\item
Soporte para escribir y administrar módulos remotos
y para la transferencia de clases y módulos entre máquinas.

\item
Un protocolo extensible
\end{itemize}

\section{Métodos útiles para el usuario de \texttt{Bench::Test}}

El módulo \texttt{Bench::Test::Remote} hace uso de la clase
\texttt{GRID::Machine} para establecer las conexiones y lanzar
las ejecuciones en las máquinas remotas.

El usuario puede definir en la creación del objeto
\texttt{Bench::Test::Remote} dos parámetros \texttt{PREAMBLE} y
\texttt{POSTAMBLE} útiles para preparar y liberar los entornos
de ejecución. Se tratan de dos referencias a rutina que reciben
como único parámetro el objeto de la clase \texttt{GRID::Machine}
utilizado para establecer la conexión.

Gracias a ello, el usuario dispone de toda la funcionalidad
de \texttt{GRID::Machine} para trabajar en la máquina remota.

No se pretende que el usuario conozca el 100\% de las capacidades
de éste módulo, pero es recomendable que conozca unos cuantos
métodos que le podrán ser útiles a la hora de escribir
las rutinas \texttt{PREAMBLE} y \texttt{POSTAMBLE}.

\subsection{Algunas funciones simples}

Las siguientes funciones realizan la misma operación que
sus homónimas en Perl:

\begin{itemize}
\item \texttt{chdir}
\item \texttt{getcwd}
\item \texttt{glob}
\item \texttt{mkdir}
\item \texttt{system}
\item \texttt{umask}
\end{itemize}

\subsection{La función \texttt{system}}

Ejecuta la función \texttt{system} en la máquina remota.
Véase un ejemplo:

\begin{verbatim}
   $ cat uname.pl
   #!/usr/bin/perl -w
   use strict;
   use GRID::Machine;
   
   my $host = shift || 'user@remote.host';

   my $machine = GRID::Machine->new(
                    host       => $host,
                    sendstdout => 1,
                    startdir   => 'projects'
                 );

   my $dir = $machine->getcwd->result;
   print "$dir\n";

   print $machine->system('uname -a');
\end{verbatim}

Al ejecutar este pequeño script se obtiene 
una salida similar a esta:

\begin{verbatim}
   /home/user/projects
   Linux machine 2.6.24 #1 Tue Aug 16 13:22:48 UTC 2005 i686 GNU/Linux
\end{verbatim}

Esta función puede ser muy útil a la hora de compilar
en la máquina remota ejecutando la orden \texttt{make}:

\begin{verbatim}
   $machine->chdir($project_dir);
   $machine->system('make');
\end{verbatim}

\subsection{La función \texttt{qx}}

Similar a las comillas de ejecución (\textit{backticks}).
El resultado depende del contexto. En un contexto de 
lista devuelve una lista con las líneas de la salida.
En un contexto escalar devuelve una cadena de caracteres
con la salida.

\subsection{La función \texttt{tar}}

La función \texttt{tar} es equivalente a:

\begin{verbatim}
   system('tar', $options, '-f', $file)
\end{verbatim}

Donde \texttt{\$options} es una cadena que contiene las
opciones y \texttt{\$file} el fichero que se desea
comprimir/descomprimir. 

La función devuelve el código de error proveniente de \texttt{tar}.
Véase un ejemplo:

\begin{verbatim}
   $m->tar($dist, '-xz')->ok
      or warn "$host: Can't extract files from $dist\n";
\end{verbatim}

\subsection{La función \texttt{version}}

Su sintaxis es la siguiente:

\begin{verbatim}
   $machine->version('Some::Module')
\end{verbatim}

Devuelve la versión (\texttt{VERSION}) del módulo si éste
está instalado en la máquina y posee un número de versión.

\subsection{La función \texttt{installed}}

Su sintaxis es la siguiente:

\begin{verbatim}
   $machine->installed('Some::Module');
\end{verbatim}

Devuelve \texttt{TRUE} si el módulo dado está instalado en
la máquina remota.

\subsection{Métodos \textit{File Status}}

Se trata de métodos equivalentes a las funciones de test
de ficheros:

\begin{verbatim}
   -r -w -e -x -z -s -f -d   -t -T -B -M -A -C
\end{verbatim}

Debido a que la sintaxis de Perl no permite utilizar los
guiones como nombres de función, se utiliza el \textit{underscore}
o guión bajo. Véase un ejemplo:

\begin{verbatim}
   $machine->mkdir($dir) unless $machine->_w($dir)
\end{verbatim}

\section{El script}

Como ayuda al usuario se proporciona junto con la
distribución de \texttt{Bench::Test} el script
\texttt{maketest} que facilita al usuario la
utilización del módulo. Se trata de un script
sencillo cuya tarea es crear un objeto de la
clase \texttt{Bench::Test} e invocar al método
\texttt{make\_test}. El constructor
toma los parámetros
desde un fichero de configuración que, por 
defecto, se llama \texttt{maketest.conf}.

La forma de uso es la siguiente:

\begin{verbatim}
   $ maketest [-f configfile]
\end{verbatim}


\section{Código}

A continuación se muestra el contenido íntegro
del script \texttt{maketest}:

\begin{verbatim}
   #!/usr/bin/perl -w

   use strict;
   use Pod::Usage;
   use Getopt::Long;
   use Bench::Test;
   use Carp;

   sub version {
     print "Version $Bench::Test::VERSION\n";
     exit;
   }

   sub usage {
     print "Usage:\n  $0 [-f configfile]\n";
     exit;
   }
   sub man {
     pod2usage(
       -exitval => 1,
       -verbose => 2
     );
   }

   # MAIN ==========================

   my $config_file = './maketest.conf';  #maketest.conf by default

   GetOptions(
     'version' => \&version,
     'usage'   => \&usage,
     'help'    => \&man,
     'file=s'  => \$config_file
   ) or croak usage();

   my $bench = new Bench::Test(
                      config_file => $config_file,
                   );

   $bench->make_tests;
\end{verbatim}
\section{Descripción del problema}
El cálculo del número $\pi$ es un problema con muchas posibles
soluciones y que ha sido ampliamente abordado por numerosas
técnicas de programación y de métodos numéricos. 

El área bajo la curva $y=\frac{1}{1+x^2}$ entre $0$ y $1$ nos
proporciona un método para calcular $\pi$. Véase la figura~\ref{fig:calculopi}.

\begin{displaymath}
\int_{0}^{1}\frac{4}{1+x^2}dx=4\times arctan(x) |_0^1=4(\frac{\pi}{4} - 0) = \pi
\end{displaymath}

\begin{figure}[h!]
  \label{fig:calculopi}
  \centering
    \includegraphics[width=200pt]{images/calculopi.png}
  \caption{Calculo del numero $\pi$}
\end{figure}

Esta integral puede aproximarse por la suma:

\begin{displaymath}
\pi \simeq \sum_{i=0}^{N-1} \frac{4}{N \times (1 + (\frac{i+0.5}{N})^2 )}
\end{displaymath}

Supongamos entonces que tenemos un fragmento de código C como el que sigue:

\begin{verbatim}
   w = 1.0 / N;
   pi = 0.0;
   for (i = 0; i < N; i++) {
     local = (i + 0.5)*w;
     pi = pi + 4.0/(1.0 + local*local);
   }
\end{verbatim}

Un potencial usuario podría querer introducir mejoras
en este código o comparar ejecuciones de este mismo
programa en distintas máquinas.

Los parámetros a considerar en la ejecución del programa
son el número de intervalos $N$, el tiempo de ejecución
del algoritmo, y el valor de $\pi$ calculado.

\section{Instrumentación del programa}

Para que el módulo \texttt{Bench::Test} pueda realizar su labor
correctamente el usuario del programa debe instrumentarlo
de forma que todos los parámetros que le interesen sean
devueltos por el programa, ya sea volcando 
la salida en un fichero o mostrándola por pantalla
(\textit{Standard Output}).

El objeto \texttt{Bench::Test} lanza las ejecuciones y
obtiene la salida o la lee desde un fichero para
a continuación aplicar expresiones regulares que permitan
filtrar la información deseada. Por ello, a la hora
de instrumentar el programa debemos mostrar los
datos de forma que puedan ser fácilmente reconocidos
mediante una sencilla expresión regular.

En este caso, supongamos que se instrumenta el programa
enviando los resultados a la salida estandar. El código
quedaría como sigue:

\begin{verbatim}
   gettimeofday(&t1, NULL);
  
   w = 1.0 / N;
   pi = 0.0;
   for (i = 0; i < N; i++) {
     local = (i + 0.5)*w;
     pi = pi + 4.0/(1.0 + local*local);
   }

   gettimeofday(&t2, NULL);

   /* Calculo de la duración */
   start = (double)(t1.tv_sec * 1.0e6) + (double)t1.tv_usec;
   end   = (double)(t2.tv_sec * 1.0e6) + (double)t2.tv_usec;
   diff  = (end - start) / 1.0e6;

   printf("Time: %f\n", diff);
   printf("Number of intervals: %d\n", N);
   printf("Calculated Pi: %1.20f\n", pi/N);
\end{verbatim}

\section{Parámetros de configuración}

Una vez instrumentado el programa cliente se han de
definir los parámetros que guíen las ejecuciones. Como ya
se ha explicado anteriormente en esta memoria,
para ello existen dos posibilidades:

\begin{itemize}
\item 
Escribir un script perl que cree un objeto de la clase
Bench::Test con los parámetros adecuados (véase la
documentación del módulo \texttt{Bench::Test} en el
capítulo \ref{chapter:Bench-Test}).

\item 
Utilizar el script \texttt{maketest} proporcionado junto
con el modulo \texttt{Bench::Test} y definir los parámetros
mediante un fichero de configuración cuyo nombre, por defecto,
es \texttt{maketest.conf} (véase la documentacion del
script \texttt{maketest} en el capítulo
\ref{chapter:maketest}).
\end{itemize}

La forma más sencilla para un usuario sin conocimientos
de Perl es escribir el fichero de configuración y hacer
uso del script proporcionado.

A continuación empezamos a escribir, paso a paso, el
fichero de configuración.

\section{Expresiones regulares}

La primera acción que realiza el objeto \texttt{Bench::Test}
después de cada ejecución es aplicar las expresiones
regulares sobre la salida generada por el programa
del usuario.

Estas expresiones definen los parámetros de estudio
en los que el usuario está interesado.

Para definirlas, se utiliza el array \texttt{@TABLE} y se
debe tener en cuenta el formato de salida del programa.

El resultado de una ejecución de nuestro programa
tendría un aspecto similar a éste:

\begin{verbatim}
   ~/Bench-Test/examples/pi$ ./pi 50000000
   Time: 0.644815
   Number of intervals: 50000000
   Calculated Pi: 3.14159265358952710656
\end{verbatim}

Para filtrar dicha salida el array \texttt{@TABLE}
debería tener la siguiente forma:

\begin{verbatim}
   @TABLE = (
      TIME => 'Time:\s+(.*?)\n',
      NOI  => 'Number of intervals: (.*?)\n',
      PI   => 'Calculated Pi: (.*?)\n',
   );
\end{verbatim}

Obsérvese que el array \texttt{@TABLE} esta formado por
pares clave-valor cuya clave indica el nombre que el
usuario desea dar al campo objeto de estudio y cuyo
valor puede ser de dos tipos:

\begin{description}
\item[{\textbf{Cadena de caracteres:}}] \mbox{}

Contiene la expresión regular que permite filtrar la salida.
Debe estar parentizada en el lugar donde se encuentre el
campo que se desea filtrar.

\item[{\textbf{Referencia a rutina:}}] \mbox{}

En lugar de aplicar una expresión regular sobre la salida
se deja al usuario la responsabilidad del filtrado. La rutina
recibe como como parámetro la salida intacta del programa.
Este campo es muy útil a la hora de combinar varios resultados
en un solo campo.
\end{description}

\section{Parámetros de ejecución}

Una vez definidas las expresiones regulares que filtrarán
la salida del programa, es hora de indicar los parámetros
de ejecución.

Para ello se define el array \texttt{@TESTS} que, en este caso,
podría tener un aspecto similar a éste:

\begin{verbatim}
   @TESTS = (
      pi100000 =>    '100000',
      pi200000 =>    '200000',
      pi500000 =>    '500000',
      pi1000000 =>   '1000000',
   );
\end{verbatim}

Esta definición generaría cuatro ejecuciones de la forma:

\begin{verbatim}
   $ <ejecutable>  100000
   $ <ejecutable>  200000
   $ <ejecutable>  500000
   $ <ejecutable>  1000000
\end{verbatim}

Nótese que el array \texttt{@TESTS} está formado
por pares clave-valor. El valor indica el nombre
del test correspondiente. El nombre de este test estará
disponible al usuario como un campo llamado \texttt{NAME}
en la tabla final, como si hubiera sido definido en el
array \texttt{@TABLE}.

\section{Entornos de ejecución}

Todavía no se han definido en el fichero de configuración
los parámetros relacionados con el ejecutable y los entornos
de ejecución (máquinas remotas, conexiones). Para ello se utiliza
hash \texttt{\%EXPERIMENTS}.

El hash \texttt{\%EXPERIMENTS} está formado por pares clave-valor
cuyas claves son el nombre que el usuario quiere dar a
sus entornos de ejecución (por ejemplo, nombre de la máquina
donde se está ejecutando), y cuyo valor es una referencia
a un objeto de la clase \texttt{Bench::Test::Base}, \texttt{Bench::Test::Local}
o \texttt{Bench::Test::Remote}.

Para este ejemplo podríamos definir el hash \texttt{\%EXPERIMENTS} de
la siguiente forma:

\begin{verbatim}
   %EXPERIMENTS = (
      'FEB07'    => Bench::Test::Base->new (
                       WORKDIR   => './FEB07'
                 ),
      'LOCAL'    => Bench::Test::Local->new  (
                       WORKDIR   => '.',
                       EXECUTABLE => './pi',
                    ),
      'ORION'    => Bench::Test::Remote->new (
                       HOST       => 'user@host',
                       WORKDIR    => '/home/user/mm',
                       EXECUTABLE => 'pi',
                    ),
   );
\end{verbatim}

Esta definición contiene los tres posibles objetos: \texttt{Bench::Test::Base},
\texttt{Bench::Test::Local} y \texttt{Bench::Test::Remote}. La función de estos objetos
es definir los parámetros de ejecución en máquina local, remota o acceder
a resultados de ejecuciones anteriores.

\subsection{Objeto \texttt{Bench::Test::Base}}

El objeto \texttt{Bench::Test::Base} recibe como único parámetro
en el constructor el nombre del directorio en donde se encuentran
almacenados los ficheros con las salidas de las ejecuciones
anteriores con las que queremos comparar.

El nombre del archivo a leer consiste en nombre del \texttt{test} con la
extension \texttt{.base} al final. El nombre del test se ha definido
anteriormente como clave de los pares almacenados en el array \texttt{@TEST}.

\subsection{Objeto \texttt{Bench::Test::Local}}

El objeto \texttt{Bench::Test::Local} se encarga de las ejecuciones en la 
máquina local. Su constructor recibe como parámetros el directorio
de trabajo donde se encuentra el ejecutable y el nombre del ejecutable.

\subsection{Objeto \texttt{Bench::Test::Remote}}

El objeto \texttt{Bench::Test::Remote} permite las ejecuciones en máquinas
remotas. Su constructor recibe como parámetros el nombre del host
(y usuario, si hiciera falta) donde se van a lanzar las ejecuciones.
También recibe el directorio de trabajo y el ejecutable en la
máquina remota.

Si el directorio de trabajo y el ejecutable no se encuentran en
la máquina remota, pueden definirse dos parámetros (\texttt{PREAMBLE} y
\texttt{POSTAMBLE}) que permiten al usuario subir archivos y ejecutar
comandos en dicha máquina. Se trata de dos referencias a rutina
que reciben como parámetro una referencia al objeto
\texttt{GRID::Machine} con el que se ha establecido la conexión con
la máquina remota.

El módulo \texttt{GRID::Machine} permite subir archivos y ejecutar comandos
en la máquina remota con la que ha establecido conexión a través
de SSH. Véase la do\-cu\-men\-ta\-ción de \texttt{GRID::Machine} para conocer
éstas y muchas otras funcionalidades.

\section{Validez de los tests}

Cada ejecución realizada genera un campo llamado \texttt{TEST} que
indica si el test es válido (\textit{ok}) o no válido (\textit{Fail}).
El usuario puede indicar la condición de validez de un test mediante la
rutina \texttt{Bench::Test::Entry::is\_ok}. Esta rutina recibe como
parámetro el objeto de la clase \texttt{Bench::Test::Entry} asociado al
test en cuestión. Este objeto tiene disponibles todos los valores
de los campos definidos por el usuario en el array \texttt{@TABLE} y
algunos otros métodos muy útiles. 

Un test se considera válido cuando la rutina \texttt{Bench::Test::Entry::is\_OK}
devuelve un valor verdadero. Si no fuera vital validar las ejecuciones, el usuario
podría escribir la rutina de forma que el resultado siempre fuese
válido:

\begin{verbatim}
   sub Bench::Test::Entry::is_OK {
      return 1;
   }
\end{verbatim}

En el cálculo del número $\pi$ sí es fundamental validar el resultado.
La rutina de validación de las ejecuciones podría tener el siguiente
aspecto:

\begin{verbatim}
   sub Bench::Test::Entry::is_OK {
      my $self = shift;
      my $pi = $self->get_field_value('PI');
      my $error = $pi - 3.14159265358979323846;

      return 1 if ( abs($error) < 0.001 );
      return 0;
   }
\end{verbatim}

En este ejemplo, se dan por válidos los tests que devuelven un valor
de $\pi$ con una error absoluto menor que $0.0001$.

\section{¿Qué campos mostrar?}

Es posible que en algún momento queramos ver u ocultar alguno
de los campos que hemos especificado en el array \texttt{@TABLE}. Para
ello se utiliza el array \texttt{@VISUAL}.

El array \texttt{@VISUAL} contiene una lista con los nombres de los
campos que queremos que aparezcan en la siguiente tanda de
ejecuciones. Por ejemplo:

\begin{verbatim}
   @VISUAL = ('TEST', 'NAME', 'NOI', 'TIME', 'PI');
\end{verbatim}

Otra forma más cómoda de escribir el array \texttt{@VISUAL} es
utilizar del operador \texttt{qw} de Perl:

\begin{verbatim}
   @VISUAL = qw(TEST NAME NOI TIME PI);
\end{verbatim}

En este caso se estaría indicando que se muestren
el número de intervalos utilizados para calcular el valor de $\pi$
(\texttt{NOI}), el tiempo de ejecución (\texttt{TIME}) y el valor de
$\pi$ obtenido con el programa (\texttt{PI}).
Los campos \texttt{TEST} y \texttt{NAME} son dos campos que se generan
automáticamente y que contienen el nombre del test y el resultado
(\textit{ok} o \textit{Fail}).

\section{Campos invariables}

Muchas veces ocurre que algunos campos son independientes del 
lugar donde se realizan las ejecuciones. En nuestro ejemplo,
el número de intervalos y el valor de $\pi$ son los mismos en la
máquina local que en la máquina remota puesto que el algoritmo
es el mismo. Para evitar que se muestren estos valores para ambas
máquinas se incluyen dichos campos en el array \texttt{@UNIQUE}:

\begin{verbatim}
   @UNIQUE = qw(NOI PI);
\end{verbatim}

\section{¿En qué máquinas ejecutar?}

Al igual que con los campos filtrados y el array \texttt{@VISUAL}, también
sería deseable poder evitar que se realicen ejecuciones en ciertas máquinas. En
el array \texttt{@SELECTED} se indican los nombres de los \texttt{EXPERIMENTS}
(máquinas) en los que se desea lanzar las ejecuciones. Por ejemplo:

\begin{verbatim}
   @SELECTED = qw(FEB07 LOCAL ORION);
\end{verbatim}

Al incluir todos los \texttt{EXPERIMENTS} se indica que se desea realizar 
las ejecuciones en todas las máquinas definidas anteriormente. Si no se quisiera
ejecutar en la máquina remota \texttt{ORION} , el array \texttt{@SELECTED} tendría la
siguiente forma:

\begin{verbatim}
   @SELECTED = qw(FEB07 LOCAL);
\end{verbatim}

\section{Formato de salida}

Por último, sólo queda definir el formato de salida con el 
array \texttt{@OUTPUTFORMAT}. A continuación un ejemplo:

\begin{verbatim}
   @OUTPUTFORMAT = (
      'text'  => '',
      'html'   => 'output.html',
   );
\end{verbatim}

Se trata de un hash cuyas claves indican el formato en el
que se quiere la salida y cuyo valor especifica el fichero
a donde se debe enviar la salida con dicho formato. Si se deja
el valor en blanco la salida se muestra por pantalla.

Los formatos disponibles son \texttt{text} (texto plano), \texttt{xml},
\texttt{html} y \texttt{latex}. Además es posible que el usuario provea
un nuevo formato mediante la clave \texttt{file:fichero.tt} donde
\texttt{fichero.tt} es el nombre del fichero en el que el usuario
ha escrito su plantilla con Template Toolkit. 

Para poder formatear la salida se debe esperar hasta que
se realice la última ejecución. Sin embargo,
se muestran por pantalla línea a línea los resultados de
cada ejecución formateados con simples tabuladores.

\newpage

\section{Fichero de configuración}

El fichero de configuración quedaría como sigue:

\begin{small}
\begin{verbatim}
   @TABLE = (
      TIME => {  REGEXP => 'Time:\s+(.*?)\n' },
      NOI  => {  REGEXP => 'Number of intervals: (.*?)\n' },
      PI   => {  REGEXP => 'Calculated Pi: (.*?)\n' },
   );
\end{verbatim}
\begin{verbatim}
   @TESTS = (
      pi100000 =>    '100000',
      pi200000 =>    '200000',
      pi500000 =>    '500000',
      pi1000000 =>   '1000000',
   );
\end{verbatim}
\begin{verbatim}
   %EXPERIMENTS = (
      'FEB07'     => Bench::Test::Base->new (
                       WORKDIR   => './FEB07'
                 ),
      'LOCAL'    => Bench::Test::Local->new  (
                       WORKDIR   => '.',
                       EXECUTABLE => './pi',
                    ),
      'ORION'    => Bench::Test::Remote->new (
                       HOST       => 'user@host',
                       WORKDIR    => '/home/user/pi',
                       EXECUTABLE => 'pi',
                    ),
   );
\end{verbatim}
\begin{verbatim}
   sub Bench::Test::Entry::is_OK {
      my $self = shift;
      my $pi = $self->get_field_value('PI');

      if ( ($pi - 3.141592) < 0.0001 ) {
         return 1;
      }
      return 0;
   }
\end{verbatim}
\begin{verbatim}
   @VISUAL   = qw(TEST NAME NOI TIME PI);
   @UNIQUE   = qw(NOI PI);
   @SELECTED = qw(FEB07 LOCAL ORION);
\end{verbatim}
\begin{verbatim}
   @OUTPUTFORMAT = (
      'text'  => '',
      'html'   => 'output.html',
   );
\end{verbatim}
\end{small}

\section{Resultado}

Una ejecución del script \texttt{maketest} con el fichero de configuración
anteriormente descrito daría como resultado algo como:

\begin{small}
\begin{verbatim}
   $ ./maketest 
   TEST    NAME    NOI  TIME(FEB07)   TIME(LOCAL)  PI(FEB07)   PI(LOCAL)
   ok      pi100000     100000  0.004671    0.004674   3.141593   3.141593
   ok      pi200000     200000  0.009338    0.010051   3.141593   3.141593
   ok      pi500000     500000  0.023357    0.019483   3.141593   3.141593
   ok      pi1000000    1000000 0.042296    0.022002   3.141593   3.141593
   TEST  NAME       NOI      TIME(FEB07)  TIME(LOCAL)  PI(FEB07)  PI(LOCAL)  
   ok    pi100000   100000   0.004671     0.004674     3.141593   3.141593   
   ok    pi200000   200000   0.009338     0.010051     3.141593   3.141593   
   ok    pi500000   500000   0.023357     0.019483     3.141593   3.141593   
   ok    pi1000000  1000000  0.042296     0.022002     3.141593   3.141593   
\end{verbatim}
\end{small}

La primera tabla se va generando ejecución a ejecución
mientras que la segunda se muestra al final de todas las ejecuciones
para ser formateada correctamente.

\begin{figure}
  \centering
    \includegraphics[width=\textwidth]{images/outputhtml.png}
  \caption{Salida en formato HTML vista en un navegador}
  \label{fig:outputhtml}
\end{figure}

Además, como se especificó en el array \texttt{@OUTPUTFORMAT} se crea un archivo
\texttt{output.html} cuyo aspecto puede verse en la figura~\ref{fig:outputhtml}.


\section{Nombre}

\texttt{Bench::Test::Remote}

Automatiza ejecuciones en máquinas remotas

\section{Sinopsis}

\begin{verbatim}
   my $remote = Bench::Test::Remote->new(
      HOST       => 'user@some.host.com',
      WORKDIR    => '/home/user/mm',
      EXECUTABLE => 'mm',
      BASEDIR    => './base_somehost',
      OUTPUTFILE => 'output.dat',
      PREAMBLE   => sub {
         my $machine = shift;
         $machine->put(['mm.tar.gz']);
         $machine->system('tar xfz mm.tar.gz');
         $machine->chdir('mm');
         $machine->system('make');
      },
      POSTAMBLE  => sub {
         my $machine = shift;
         $machine->chdir('..');
         $machine->system('rm -rf mm');
         $machine->system('rm mm.tar.gz');
      },
   );
\end{verbatim}
\begin{verbatim}
   my $parameters = ...
   my $output = $remote->get_result($parameters);
\end{verbatim}
\begin{verbatim}
   $remote->save_result($parameters, $testname);
\end{verbatim}

\section{Descripción}

El objeto \texttt{Bench::Test::Remote} permite ecapsular las operaciones
de ejecución de programas en máquinas remotas. Dispone de dos
métodos que permiten obtener la salida de la ejecución o almacenarla
respectivamente: \texttt{get\_result} y \texttt{save\_result}.

El objeto \texttt{Bench::Test} hace uso del módulo \texttt{GRID::Machine}
escrito por \textbf{Casiano Rodríguez León}.

\subsection{Un ejemplo}

Supongamos un programa cuya salida sea la siguiente:

\begin{verbatim}
   user@some.host.com:~/projects/Bench-Test/examples/mm$ ./mm dat/mm_200.dat 
   Filas primera matriz: 200
   Filas segunda matriz: 200
   Columnas segunda matriz: 200
   Time of product: 0.210942
   Result: 4102
\end{verbatim}

Creamos un objeto \texttt{Bench::Test::Remote} de la siguiente forma:

\begin{verbatim}
   my $remote = Bench::Test::Remote->new(
      HOST       => 'user@some.host.com',
      WORKDIR    => '/home/user/mm',
      EXECUTABLE => 'mm',
      BASEDIR    => './base_somehost',
      OUTPUTFILE => 'output.dat',
      PREAMBLE   => sub {
         my $machine = shift;
         $machine->put(['mm.tar.gz']);
         $machine->system('tar xfz mm.tar.gz');
         $machine->chdir('mm');
         $machine->system('make');
      },
      POSTAMBLE  => sub {
         my $machine = shift;
         $machine->chdir('..');
         $machine->system('rm -rf mm');
         $machine->system('rm mm.tar.gz');
      },
   );
\end{verbatim}

Con una llamada a \texttt{get\_result} como la que sigue:

\begin{verbatim}
   my $output = $remote->get_result('dat/mm_200');
\end{verbatim}

Obtendríamos en \texttt{\$output} una salida similar. En cambio,
con una llamada a \texttt{save\_result} como esta:

\begin{verbatim}
   $remote->save_result('dat/mm_200', 'test200');
\end{verbatim}

La salida del programa sería almacenada en el fichero
\texttt{test200.base} dentro del directorio definido en la
llamada al constructor como \texttt{BASEDIR}, en la máquina local.

\section{Métodos}

\subsection{El constructor \texttt{new}}

Véase una llamada típica:

\begin{verbatim}
   my $remote = Bench::Test::Remote->new(
      HOST       => 'user@some.host.com',
      WORKDIR    => '/home/user/mm',
      EXECUTABLE => 'mm',
      BASEDIR    => './base_somehost',
      OUTPUTFILE => 'output.dat',
      PREAMBLE   => sub { ..preamble code.. },
      POSTAMBLE  => sub { ..postamble code.. },
   );
\end{verbatim}


Este método devuelve una nueva instancia de un objeto
de la clase \texttt{Bench::Test::Remote}.

El constructor acepta los siguientes parámetros:

\begin{description}

\item[{\texttt{HOST:}}] \mbox{}

Máquina de destino sobre las que se lanzaran las
ejecuciones. Para un correcto funcionamiento se debe
tener acceso no interactivo mediante el mecanismo
clave publica-privada. 

\item[{\texttt{WORKDIR:}}] \mbox{}

Directorio de trabajo donde se encuentra 
el ejecutable y desde donde se llevarán a cabo todas las ejecuciones.

\item[{\texttt{EXECUTABLE:}}] \mbox{}

Nombre del fichero ejecutable.

\item[{\texttt{OUTPUTFILE:}}] \mbox{}

Parámetro opcional que indica el nombre del fichero
donde se encuentra la salida de la ejecucion del programa. Se 
utiliza cuando el programa vuelca la salida en un fichero
en lugar de mostrarla por pantalla.

\item[{\texttt{BASEDIR:}}] \mbox{}

Nombre del directorio donde se creará el fichero \texttt{.base}
generado como consecuencia de una llamada a \texttt{save\_result}.

\item[{\texttt{PREAMBLE} y \texttt{POSTAMBLE:}}] \mbox{}

Referencia a rutinas que seran llamadas justo después de
abrir y antes de cerrar la conexión con la máquina remota
respectivamente.

Ambas rutinas reciben como parámetro el objeto \texttt{GRID::Machine}
asociado a la máquina remota. Véase la documentación del módulo
\texttt{GRID::Machine} para conocer sus posibilidades.

\end{description}

\subsection{El método \texttt{get\_result}}

Véase una llamada típica:

\begin{verbatim}
   my $parameters = '-n 20 -p';
   my $output = $remote->get_result($parameters);
\end{verbatim}

El método \texttt{get\_result} acepta como único parámetro
una cadena de caracteres que contiene
los parámetros con los que se ejecutará el experimento
indicado en el constructor con el parámetro \texttt{EXECUTABLE} en
la máquina remota indicada con el parámetro \texttt{HOST}.

\subsection{El método \texttt{save\_result}}

Véase una llamada típica:

\begin{verbatim}
   $remote->save_result($parameters, $testname);
\end{verbatim}

El método \texttt{save\_result} acepta igual que \texttt{get\_result} una
cadena de caracteres con los parámetros de ejecución y el
nombre del test correspondiente.

El método \texttt{save\_result} automatiza la ejecución invocando
al método \texttt{get\_result} y guardando la salida en un fichero
de texto ubicado en el directorio definido en el constructor
con el parámetro \texttt{BASEDIR}. El nombre del archivo se
obtiene concatenando el parámetro \texttt{\$testname} con la
extensión \texttt{.base}.

\section{Véase también}

Para una mejor comprensión del módulo \texttt{Bench::Test::Remote},
véase también la documentación de los siguientes módulos:

\begin{itemize}
\item \texttt{Bench::Test}
\item \texttt{Bench::Test::Base}
\item \texttt{Bench::Test::Local}
\item \texttt{GRID::Machine}
\end{itemize}
\section{Autenticación por clave pública-privada}

Para que el módulo \texttt{GRID::Machine} y, en consecuencia,
el módulo \texttt{Bench::Test} trabajen correctamente, es necesario
que las máquinas remotas sobre las que se desea lanzar las ejecuciones
permitan una autenticación automática con SSH. En los siguientes
apartados se
detalla el procedimiento a seguir para establecer conexiones automáticas
entre la máquina local y una máquina remota. Esta información ha sido
extraída de la documentación del módulo \texttt{GRID::Machine} escrito
por \textbf{Casiano Rodríguez León} \cite{CasianoGridMachineDoc}.

\subsection{Generación de claves}

El primer paso para establecer la autenticación automática entre dos
máquinas es generar una clave pública. Para ello se utiliza el
comando \texttt{ssh-keygen}:

\begin{verbatim}
   $ ssh-keygen -t rsa -N ''
\end{verbatim}

La opción \texttt{-t} indica el tipo de clave que se desea generar.
Existen tres tipos de claves: \textit{rsa1}, \textit{rsa}, y \textit{dsa}.
La opción \texttt{-N} establece el \textit{passphrase}. Es muy útil dejarlo
vació cuando se usa con restricciones de clave o cuando se trabaja con
comandos por lotes y procesamiento automático como en este caso.

Por defecto, las claves pública y privada generadas, se almacenan en
los ficheros \texttt{\$HOME/.ssh/id\_rsa} y
\texttt{\$HOME/.ssh/id\_rsa.pub} respectivamente.

El contenido del fichero \texttt{id\_rsa.pub} es algo similar a esto:

\begin{verbatim}
   ssh-rsa AAAAB3NzaC1ycAAABIwAAAIEArkwv9X8eTVK4F7pMlSt45pWoiakFkZMw
   G9BjydOJPGH0RFNAy1QqIWv7vS5K2tr+EEO+F8WL2Y/jK4ZkUoQgoi+n7DWQVOHsR
   ijcS3LvtO+50Np4yjXYWJ9JL6GHcp8o7+YKEyVUMB2CSDOP99eF9g5Q0d+1U2WVdB
   WQM= user@host
\end{verbatim}

\subsection{Instalar la clave pública}

Una vez generado el par de claves, se debe instalar la clave pública en la
máquina remota. Para ello, se añade la clave pública generada (el contenido
del fichero \texttt{id\_rsa.pub}) al final del fichero
\texttt{/home/user/.ssh/authorized\_keys} en la máquina remota. Si está disponible
el script \texttt{ssh-copy-id} se podría hacer de la siguiente forma:

\begin{verbatim}
   $ ssh-copy-id -i ~/.ssh/id_rsa.pub user@remote.machine
\end{verbatim}

Otra forma de hacerlo podría ser ejecutar el siguiente comando:

\begin{small}
\begin{verbatim}
$ ssh machine "umask 077; cat >> .ssh/authorized_keys" < .ssh/id_rsa.pub
\end{verbatim}
\end{small}

Una última opción es hacerlo a mano:

\begin{verbatim}
   $ scp .ssh/id_rsa.pub remote.machine:~/

   $ cat id_rsa.pub >> .ssh/authorized_keys
\end{verbatim}

El primer comando se debe ejecutar en la máquina local para copiar el
archivo a la máquina remota, y el segundo se ejecuta en la máquina
remota para volcar el contenido del fichero \texttt{id\_rsa.pub} al
final del fichero \texttt{authorized\_keys}.

\subsection{Comprobación}

Una vez instalada la clave pública en la máquina remota, se debería
ser capaz de autenticarse sin contraseña utilizando la clave privada:

\begin{verbatim}
   $ ssh remote.machine
   Linux remote.machine 2.6.15-1-686-smp #2 SMP Mon Mar 6 15:34:50 UTC
   Last login: Sat Jul  7 13:34:00 2008 from local.machine
   user@remote.machine:~$       
\end{verbatim}

También podrían ejecutarse comandos automáticamente en el servidor
remoto:

\begin{verbatim}
   $ ssh remote.machine uname -n
   remote.machine
\end{verbatim}
\section{Nombre}

\texttt{Bench::Test}

Automatización y análisis de ejecuciones.

\section{Sinopsis}

\begin{verbatim}
   use Bench::Test;
\end{verbatim}
\begin{verbatim}
   # New Bench::Test usando un fichero de configuración
   my $bt = Bench::Test->new(
      config_file => 'maketest.conf'
   );
\end{verbatim}
\begin{verbatim}
   # New Bench::Test especificando todos los parámetros a mano
   my $bt = Bench::Test->new(
       tests       => \@TESTS,
       table       => \@TABLE,
       visual      => \@VISUAL,
       experiments => \%EXPERIMENTS,
       selected    => \@SELECTED,
   );
\end{verbatim}
\begin{verbatim}
   # Executando "make test"
   $bt->make_test;
\end{verbatim}
\begin{verbatim}
   # Executando "create test"
   $bt->create_tests;
\end{verbatim}

\section{Descripción}

El objeto Bench::Test permite automatizar, analizar y comparar
diversas ejecuciones realizadas en tiempo real o en el pasado y 
en la máquina local y/o máquinas remotas simultáneamente. Cuenta con
dos métodos principales: \texttt{make\_test} y \texttt{create\_tests}.

Los parámetros de configuración de las ejecuciones pueden 
definirse mediante un fichero de configuración (por defecto,
maketest.conf) o mediante parámetros en el constructor.

La salida de las ejecuciones es filtrada mediante un
conjunto de expresiones regulares indicadas por el usuario.
El resultado es devuelto al usuario por pantalla.

\subsection{Un ejemplo}

Supongamos un programa cuya salida sea la siguiente:

\begin{verbatim}
   ~/projects/Bench-Test/examples/mm$ ./mm dat/mm_200.dat 
   Filas primera matriz: 200
   Filas segunda matriz: 200
   Columnas segunda matriz: 200
   Time of product: 0.210942
   Result: 4102
\end{verbatim}

Supongamos que queremos ejecutar dicho programa con
diferentes parámetros de entrada y comparar las salidas.

La idea es que el usuario especifique las caracteristicas
del experimento y ejecute el método \texttt{make\_test}. El método
realizará las ejecuciones para cada conjunto de parámetros,
analizará las salidas, las formateará y las devolverá al usuario
por pantalla o sobre ficheros.

Ejecutando el script \texttt{maketest}:

\begin{verbatim}
   #!/usr/bin/perl -w
\end{verbatim}
\begin{verbatim}
   use strict;
   use Pod::Usage;
   use Getopt::Long;
   use Bench::Test;
   use Carp;
\end{verbatim}
\begin{verbatim}
   # MAIN ======================
\end{verbatim}
\begin{verbatim}
   my $config_file = './maketest.conf';   # By default is 'maketest.conf'
\end{verbatim}
\begin{verbatim}
   my $bench = new Bench::Test(
     config_file => $config_file,
   );
\end{verbatim}
\begin{verbatim}
   $bench->make_tests;
\end{verbatim}

Se obtiene una salida similar a la siguiente:

\begin{verbatim}
   ~/projects/Bench-Test/examples/mm$ maketest
   TEST    FILE    DIM             TIME(BASE_feb)  TIME(LOCAL)     TIME(ORION)
   OK      mm_100  100:100:100     0.011588        0.026716        0.011582
   OK      mm_200  200:200:200     0.091474        0.202479        0.092152
   OK      mm_300  300:300:300     0.432486        1.000445        0.432919
   OK      mm_500  500:500:500     3.923428        5.067983        2.547144
\end{verbatim}

\section{Métodos}
\subsection{El constructor \texttt{new}}

Véase una llamada típica:

\begin{verbatim}
   # New Bench::Test usando un fichero de configuración
   my $bt = Bench::Test->new(
      config_file => 'maketest.conf'
   );
\end{verbatim}
\begin{verbatim}
   # New Bench::Test especificando todos los parámetros a mano
   my $bt = Bench::Test->new(
       tests       => \@TESTS,
       table       => \@TABLE,
       visual      => \@VISUAL,
       experiments => \%EXPERIMENTS,
       selected    => \@SELECTED,
   );
\end{verbatim}

Este método devuelve una nueva instancia de un objeto
\texttt{Bench::Test}.

Los parámetros de configuracion pueden ser expresados
en un fichero de con\-fi\-gu\-ra\-ción, con parámetros
del constructor o con ambos. En caso de conflicto
tienen mayor prioridad los parámetros definidos en 
el constructor y no en el fichero de configuración.

Los nombres de los parámetros son exactamente los 
mismos en el constructor y en el fichero de configuracion
excepto que en el fichero se escriben en mayúsculas.

\subsection{El método \texttt{make\_test}}

El método \texttt{make\_test} se encarga de automatizar las ejecuciones
definidas previamente por el usuario. A su vez, analiza las salidas
y las formatea para mostrarlas al usuario y/o almacenarlas en 
ficheros de texto con distintos formatos.

\subsection{El método \texttt{create\_tests}}

El método \texttt{create\_tests} solamente automatiza las ejecuciones
almacenando las salidas en ficheros de texto nombrados con
extension \texttt{.base} .

\section{El fichero de configuración}

Véase un ejemplo de fichero de configuración:

\begin{verbatim}
   ~/projects/Bench-Test/examples/mm$ cat maketest.conf
\end{verbatim}
\begin{verbatim}
   @TESTS = (
      mm_100 => './dat/mm_100.dat',
      mm_200 => './dat/mm_200.dat',
      mm_300 => './dat/mm_300.dat',
     mm_500 => './dat/mm_500.dat',
   );
\end{verbatim}
\begin{verbatim}
   @TABLE         = (
      #TEST metafield
      #FILE metafield
\end{verbatim}
\begin{verbatim}
      DIM  => 'primera\s*matriz:\s*(.*)\n',
      RES  => 'Result:\s+(.*)\n', 
      TIME => 'Time of product:\s*(.*)\n',
   );
\end{verbatim}
\begin{verbatim}
   @UNIQUE   = qw(DIM);
   @VISUAL   = qw(TEST FILE DIM TIME);
   @SELECTED = qw(BASE_feb LOCAL ORION);
\end{verbatim}
\begin{verbatim}
   sub Bench::Test::Entry::is_OK { Code to check if test is OK }
\end{verbatim}
\begin{verbatim}
   %EXPERIMENTS = ( 
      'BASE_feb' => Bench::Test::Base->new ( 
                     WORKDIR   => './base_FEB'
                  ),
      'LOCAL'    => Bench::Test::Local->new  (
                     WORKDIR   => '.',
                     EXECUTABLE => './mm',
                     OUTPUTFILE => 'output.dat',
                     BASEDIR   => './base_FEB',
                  ),
      'ORION'    => Bench::Test::Remote->new (
                     HOST       => 'user@host',
                     WORKDIR    => '/home/user/mm',
                     EXECUTABLE => 'mm',
                     BASEDIR    => './base_ORION',
                     OUTPUTFILE => 'output.dat',
                     PREAMBLE   => sub {
                        my $machine = shift;
                        $machine->put(['mm.tar.gz']);
                        $machine->tar('-xf', 'mm.tar.gz')->ok
                           or die 'Error when extracting mm.tar.gz';
                        $machine->chdir('mm');
                        $machine->system('make');
                     },
                     POSTAMBLE  => sub {
                        my $machine = shift;
                        $machine->chdir('..');  
                        $machine->system('rm -rf mm');
                        $machine->system('rm mm.tar.gz');
                    },
                  ),
   );
\end{verbatim}
\subsection{El array \texttt{@TABLE}}

El array \texttt{@TABLE} se utiliza para especificar las
expresiones regulares definiendo las partes de la salida en 
las que se está interesado. La clave es el nombre del campo
(\texttt{DIM}, \texttt{TIME}, etc. en el ejemplo).

Adicionalmente puede incluirse una referencia a rutina configurable
por el usuario que permite una mayor versatilidad. 

\begin{verbatim}
   @TABLE         = (
      #TEST metafield
      #FILE metafield
\end{verbatim}
\begin{verbatim}
      DIM  => 'primera\s*matriz:\s*(.*)\n'
      RES  => 'Result:\s+(.*)\n',
      TIME => 'Time of product:\s*(.*)\n',
   );
\end{verbatim}

\subsection{El array \texttt{@TESTS}}

El array \texttt{@TESTS} contiene un par clave-valor por cada uno
de los tests que se desea realizar. Cada entrada está formada por una cadena
que indica los parámetros con los que se ejecuta el programa 
ejecutable que se está analizando (valor) y el nombre del test (clave). Ejemplo:

\begin{verbatim}
   @TESTS = (
      mm_100 => './dat/mm_100.dat',
      mm_200 => './dat/mm_200.dat',
      mm_300 => './dat/mm_300.dat',
      mm_500 => './dat/mm_500.dat',
   );
\end{verbatim}

Se proveen dos rutinas de apoyo al usuario que permiten definir
el array \texttt{@TESTS} mediante el contenido de un fichero o mediante
un \textit{glob}.

La siguiente sentencia lee el fichero \texttt{myfile.test} línea a línea
obteniendo los pares (clave,valor) separados por ':'

\begin{verbatim}
  @TESTS = get_tests_from_file('myfile.test')
\end{verbatim}

Si el contenido del fichero \texttt{myfile.test} fuera el siguiente:

\begin{verbatim}
   ~/projects/Bench-Test/examples/mm$ cat myfile.test
   test1:-n 100 test1.dat
   test2:-n 200 test2.dat
   test3:-n 300 test2.dat
\end{verbatim}

El resultado de \texttt{get\_tests\_from\_file} y, por tanto, el contenido
del array \texttt{@TESTS} sería:

\begin{verbatim}
   @TESTS = (
      test1 => '-n 100 test1.dat',
      test2 => '-n 200 test2.dat',
      test3 => '-n 300 test3.dat'
   );
\end{verbatim}

La rutina \texttt{get\_tests\_from\_glob} supone que el programa recibe
un solo parámetro: el nombre de un fichero. Por tanto, suponiendo
un directorio como el siguiente:

\begin{verbatim}
   ~/projects/Bench-Test/examples/mm/dat$ ls -l
   total 1548
   -rw-r--r-- 1 alu2807 alu2807   40212 2008-02-11 09:36 mm_100.dat
   -rw-r--r-- 1 alu2807 alu2807  160412 2008-02-11 09:36 mm_200.dat
   -rw-r--r-- 1 alu2807 alu2807  360612 2008-02-11 09:36 mm_300.dat
   -rw-r--r-- 1 alu2807 alu2807 1001012 2008-02-11 09:36 mm_500.dat
\end{verbatim}

Y una llamada como la siguiente:

\begin{verbatim}
   @TESTS = get_tests_from_glob('*.dat');
\end{verbatim}

Se obtendría el siguiente array \texttt{@TESTS}:

\begin{verbatim}
   @TESTS = (
      mm_100 => 'mm_100.dat',
      mm_200 => 'mm_200.dat',
      mm_300 => 'mm_300.dat',
      mm_500 => 'mm_500.dat'
   );
\end{verbatim}
\subsection{El array \texttt{@VISUAL}}

El array \texttt{@VISUAL} determina qué campos serán mostrados 
por pantalla y en qué orden. Los nombres de los campos
son las claves definidas en el
array \texttt{@TABLE} (\texttt{DIM}, \texttt{TIME}, etc.). Ejemplo:

\begin{verbatim}
  @VISUAL = qw(TEST FILE DIM TIME);
\end{verbatim}

Dicha definición produciría una salida como esta:

\begin{verbatim}
  ~/projects/Bench-Test/mm$ ./maketest 
  TEST    FILE    DIM     TIME(BASE_feb)  TIME(LOCAL)     TIME(ORION)
  OK      mm_100  100:100:100     0.014589        0.013538        0.009383
  OK      mm_200  200:200:200     0.109944        0.177367        0.073903
  OK      mm_300  300:300:300     0.361250        0.528413        0.359595
  OK      mm_500  500:500:500     1.934884        2.993155        1.886891
\end{verbatim}


Obsérvese que algunos de los campos están repetidos para
cada uno de los \texttt{EXPERIMENTS} y otros no. Esto es así, porque
existen campos que son invariables cualquiera que sea la máquina
donde se ejecute. Por ejemplo: la entrada de problema, las dimensiones.

Para indicar qué campos no deben duplicarse por tratarse de campos únicos
se utiliza el array \texttt{UNIQUE}.

\subsection{El array \texttt{@UNIQUE}}

Indica los campos para los que el resultado de la ejecución no varía
de una máquina a otra. Ejemplo:

\begin{verbatim}
  @UNIQUE = qw(DIM);
\end{verbatim}

\subsection{El array \texttt{@SELECTED}}

Indica los experimentos que serán ejecutados. Similar al array
\texttt{@VISUAL} pero con los experimentos.

\subsection{El hash \texttt{\%EXPERIMENTS}}

Este hash almacena la información acerca de las distintas máquinas remotas,
máquina local y resultados de ejecuciones anteriores.

La clave es el nombre que se muestra al usuario. El valor puede ser uno de 
los siguientes objetos:

\begin{itemize}
\item \texttt{Bench::Test::Base}
\item \texttt{Bench::Test::Local}
\item \texttt{Bench::Test::Remote}
\end{itemize}

Los tres objetos cuentan con constructores distintos, pero dos métodos
idénticos, con la misma interfaz:

\begin{itemize}
\item \texttt{get\_result  (\$params, \$test)}
\item \texttt{save\_result (\$params, \$test)}
\end{itemize}

Estos métodos se encargan de devolver el resultado de la ejecución
del programa del usuario con los parámetros especificados en \texttt{\$params}
(\texttt{get\_result}) o almacenarlo en el correspondiente archivo \texttt{.base} (\texttt{save\_result}).

El parámetro \texttt{\$test} se utiliza únicamente en el objeto \texttt{Bench::Test::Base}
e indica el nombre del test al que se quiere acceder. El resultado de
la salida de una ejecución anterior estara almacenado en el fichero \texttt{\$test.base}
dentro del directorio \texttt{WORKDIR} de dicho objeto.

\subsection{El objeto \texttt{Bench::Test::Base}}

Su constructor acepta un único parámetro (\texttt{WORKDIR}) y es obligatorio. Este parámetro
indica el directorio donde se encuentran los fichero \texttt{.base} (salidas de
las ejecuciones almacenadas).

\subsection{El objeto \texttt{Bench::Test::Local}}

Su constructor acepta los siguientes parámetros:

\begin{description}

\item[{\texttt{WORKDIR}}] \mbox{}

Indica el directorio de trabajo del proyecto.


\item[{\texttt{EXECUTABLE}}] \mbox{}

Nombre del fichero ejecutable. Ruta relativa a partir
del directorio de trabajo.

\item[{\texttt{BASEDIR}}] \mbox{}

Opcional. Indica el directorio donde se almacenaran
los ficheros \texttt{.base} en caso de querer crearlo.

\item[{\texttt{OUTPUTFILE}}] \mbox{}

Opcional. Nombre del fichero de donde se leerá la
salida del programa. Si no se especifica, se toma
la salida por \texttt{stdout}.

\end{description}

\subsection{El Objeto \texttt{Bench::Test::Remote}}

Su constructor acepta los siguientes parámetros:

\begin{description}

\item[{\texttt{WORKDIR}}] \mbox{}

Mismo significado que para \texttt{Bench::Test::Local}.


\item[{\texttt{EXECUTABLE}, \texttt{BASEDIR}, \texttt{OUTPUTFILE}}] \mbox{}

Mismo significado que para \texttt{Bench::Test::Local}.


\item[{\texttt{HOST}}] \mbox{}

Usuario y host de la máquina remota con el formato \texttt{user@host}.

\item[{\texttt{PREAMBLE}}] \mbox{}

Rutina que será ejecutada antes de realizar los tests. Se
ejecuta en la máquina local, pero se le pasa un objeto de tipo
\texttt{GRID::Machine} conectado a la máquina remota, con lo que se le
permite al usuario aprovechar toda su funcionalidad.

\item[{\texttt{POSTAMBLE}}] \mbox{}

Idéntico a \texttt{PREAMBLE} salvo que se ejecuta después de haber
realizado todos los tests.

\end{description}

\section{Véase también}

Para una mejor comprensión del módulo \texttt{Bench::Test}, véase también la
documentación de los siguientes módulos:

\begin{itemize}
\item \texttt{Bench::Test::Base}
\item \texttt{Bench::Test::Local}
\item \texttt{Bench::Test::Remote}
\item \texttt{Bench::Test::Entry}
\item \texttt{Bench::Test::View}
\item \texttt{GRID::Machine} 
\end{itemize}
\section{Nombre}

\texttt{Bench::Test::View}

Formatea tablas de datos

\section{Sinopsis}

\begin{verbatim}
   my $view = Bench::Test::View->new(
      format => 'html',
      verbose => 1,
   );
\end{verbatim}
\begin{verbatim}
   my $row = [1, 2, 33];
\end{verbatim}
\begin{verbatim}
   $view->add_row($row);
\end{verbatim}
\begin{verbatim}
   my $output = $view->process;
\end{verbatim}

\section{Descripción}

El objeto \texttt{Bench::Test::View} permite formatear una tabla de
datos cualesquiera en los siguientes formatos: HTML, XML, LaTex,
texto plano o cualquier otro formato que el usuario defina utilizando
Template Toolkit.

\subsection{Un ejemplo}

Supongamos una tabla de datos como la siguiente:

\begin{verbatim}
  $data = [ [1, 2, 3], [4, 66, 7], ['yes', 1000, 'OK'] ];
\end{verbatim}

El siguiente código introduce las filas una a una y devuelve
la salida formateada en los distintos formatos disponibles.

\begin{verbatim}
  my $view = Bench::Test::View->new;
  for my $row (@{$data}) {
     $view->add_row($row);
  }
\end{verbatim}
\begin{verbatim}
  my $output_HTML  = $view->process('html');
  my $output_XML   = $view->process('xml');
  my $output_LaTex = $view->process('latex');
  my $output_text  = $view->process('text');
  my $output_user  = $view->process('file:template.tt');
\end{verbatim}
\begin{verbatim}
  print $output_text;
\end{verbatim}

La ejecución del anterior fragmento de código mostraría lo siguiente:

\begin{verbatim}
  1   2    3
  4   66   7
  yes 1000 OK
\end{verbatim}

Y además almacenaría en las diferentes variables la misma
tabla formateada con todos los formatos disponibles.

\section{Métodos}
\subsection{El constructor \texttt{new}}

El constructor acepta los siguientes parámetros:

\begin{description}

\item[{\texttt{format}}] \mbox{}

(Opcional) Formato en el que se desea la salida
formateada. Puede indicarse en el constructor o
mediante el método 'set\_format'.

\item[{\texttt{verbose}}] \mbox{}

(Opcional) Por defecto está activado. Imprime por
\texttt{stdout} las filas de datos que se van incluyendo.
Los elementos de las filas son mostrados sin formato,
solamente separados por un tabulador.

\end{description}

\subsection{El método \texttt{set\_format}}

El método \texttt{set\_format} recibe una cadena de 
caracteres que indica
el formato que se desea utilizar para formatear
la salida con el metodo \texttt{process}.

Los formatos pueden ser \texttt{html}, \texttt{xml}, \texttt{latex} y \texttt{text}.

\subsection{El método \texttt{add\_row}}

El método \texttt{add\_row} recibe una referencia a array conteniendo
una nueva fila de datos y la guarda en orden para ser mostrada
posteriormente con el método \texttt{process}

\subsection{El método \texttt{process}}

El método \texttt{process} devuelve la salida formateada con el formato
indicado en el atributo \texttt{FORMAT}. Puede recibir el formato como
parámetro si este no esta definido o si se desea cambiar
en el instante de la llamada.

\section{Formatos}

Existen cuatro formatos cuyas plantillas \textit{Template Toolkits} permanecen
almacenadas en las clases correspondientes:

\begin{itemize}
\item \texttt{html~~} en  \texttt{Bench::Test::View::HTML};
\item \texttt{xml~~~} en  \texttt{Bench::Test::View::XML};
\item \texttt{latex~} en  \texttt{Bench::Test::View::Latex};
\item \texttt{text~~} en  \texttt{Bench::Test::View::Text};
\end{itemize}

Además, se deja la posibilidad de que el usuario personalice
una plantilla y la utilice con la clase \texttt{Bench::Test::View} para
formatear sus datos. El parámetro \texttt{format} del constructor o
del metodo \texttt{set\_format} ha de ser el siguiente:

\begin{verbatim}
  'file:plantilla.tt'
\end{verbatim}

En el archivo \texttt{plantilla.tt} se encontrará la plantilla Template
Toolkit que formateará los datos. Se debe tener en cuenta lo
siguiente:

\begin{itemize}

\item 

Puede hacerse uso de la cláusula [\% PERL \%]


\item 

Los datos se encuentran en la variable \texttt{data} dentro
de la tabla de símbolos de Template Toolkit.

\end{itemize}


Véase un ejemplo de plantilla:

\begin{verbatim}
  <table>
  [% FOREACH row IN data -%]
   <tr>
      [% FOREACH item IN row -%]<td>$item</td>[%- END %]
   </tr>
  [% END -%]
  </table>
\end{verbatim}

\section{Véase también}

Para una mejor comprensión del módulo \texttt{Bench::Test::View},
véase también la documentación de los siguientes módulos:

\begin{itemize}
\item \texttt{Bench::Test}
\item \texttt{Template}
\end{itemize}
